| title | sidebar_position | id | license |
|---|---|---|---|
Custom Serializers |
4 |
custom_serializers |
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
|
For types that don't support #[derive(ForyObject)], implement the Serializer trait manually.
- External types from other crates
- Types with special serialization requirements
- Legacy data format compatibility
- Performance-critical custom encoding
use fory::{Fory, ReadContext, WriteContext, Serializer, ForyDefault, Error};
use std::any::Any;
#[derive(Debug, PartialEq, Default)]
struct CustomType {
value: i32,
name: String,
}
impl Serializer for CustomType {
fn fory_write_data(&self, context: &mut WriteContext, is_field: bool) {
context.writer.write_i32(self.value);
context.writer.write_varuint32(self.name.len() as u32);
context.writer.write_utf8_string(&self.name);
}
fn fory_read_data(context: &mut ReadContext, is_field: bool) -> Result<Self, Error> {
let value = context.reader.read_i32();
let len = context.reader.read_varuint32() as usize;
let name = context.reader.read_utf8_string(len);
Ok(Self { value, name })
}
fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> u32 {
Self::fory_get_type_id(type_resolver)
}
fn as_any(&self) -> &dyn Any {
self
}
}
// ForyDefault delegates to Default
impl ForyDefault for CustomType {
fn fory_default() -> Self {
Self::default()
}
}Note: When implementing
ForyDefaultmanually, ensure your type also implementsDefaultif you useSelf::default(). Alternatively, you can construct a default instance directly infory_default().Tip: If your type supports
#[derive(ForyObject)], you can use#[fory(generate_default)]to automatically generate bothForyDefaultandDefaultimplementations.
let mut fory = Fory::default();
fory.register_serializer::<CustomType>(100);
let custom = CustomType {
value: 42,
name: "test".to_string(),
};
let bytes = fory.serialize(&custom);
let decoded: CustomType = fory.deserialize(&bytes)?;
assert_eq!(custom, decoded);The WriteContext and ReadContext provide access to:
- writer/reader: Binary buffer operations
- type_resolver: Type registration information
- ref_resolver: Reference tracking (for shared/circular references)
// Primitive types
context.writer.write_i8(value);
context.writer.write_i16(value);
context.writer.write_i32(value);
context.writer.write_i64(value);
context.writer.write_f32(value);
context.writer.write_f64(value);
context.writer.write_bool(value);
// Variable-length integers
context.writer.write_varint32(value);
context.writer.write_varuint32(value);
// Strings
context.writer.write_utf8_string(&string);// Primitive types
let value = context.reader.read_i8();
let value = context.reader.read_i16();
let value = context.reader.read_i32();
let value = context.reader.read_i64();
let value = context.reader.read_f32();
let value = context.reader.read_f64();
let value = context.reader.read_bool();
// Variable-length integers
let value = context.reader.read_varint32();
let value = context.reader.read_varuint32();
// Strings
let string = context.reader.read_utf8_string(len);- Use variable-length encoding for integers that may be small
- Write length first for variable-length data
- Handle errors properly in read methods
- Implement ForyDefault for schema evolution support
- Type Registration - Registering serializers
- Basic Serialization - Using ForyObject derive
- Schema Evolution - Compatible mode