# pycsla-binary: Python implementation of CSLA .NET binary serialisation
# Copyright (C) 2025 Lee Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
import io
import struct
from typing import List
from .known_types import CslaKnownTypes
from .serialization_info import SerializationInfo
class CslaBinaryWriter:
"""Writes SerializationInfo objects into binary-serialised CSLA data"""
def __init__(self, stream: io.BufferedIOBase):
self.stream = stream
self.keywords_dictionary = []
def write(self, serialisation_infos: List[SerializationInfo]):
# Reverse of CslaBinaryReader.Read
self.write_int32(len(serialisation_infos))
for info in serialisation_infos:
# Write ReferenceID
self.write_int32(info.reference_id)
# Write TypeName
self.write_object_system_string(info.type_name)
# Write children
self.write_int32(len(info.children))
for child in info.children:
self.write_object_system_string(child.name)
self.write_object_bool(child.is_dirty)
self.write_object_int32(child.reference_id)
# Write field values
self.write_int32(len(info.values))
for value in info.values:
self.write_object_system_string(value.name)
self.write_object_system_string(value.enum_type_name or '')
self.write_object_bool(value.is_dirty)
self.write_object(value.value)
def write_7bit_encoded_int(self, value):
# BinaryWriter.Write7BitEncodedInt
# "The integer of the value parameter is written out seven bits at a time, starting with the seven least-significant bits. The high bit of a byte indicates whether there are more bytes to be written after this one."
while True:
value_7lsb = value & 0b01111111
value >>= 7
if value == 0:
# Final byte
self.stream.write(bytes([value_7lsb]))
return
else:
# Further bytes remaining
self.stream.write(bytes([value_7lsb | 0b10000000]))
def write_int32(self, value):
# BinaryWriter.WriteInt32
self.stream.write(struct.pack('