Skip to main content

alox_48/ser/
traits.rs

1// Copyright (c) 2024 Lily Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use super::Result;
8use crate::{BignumRef, Fixnum, Sym};
9
10/// A structure that can be serialized into ruby marshal data.
11pub trait Serialize {
12    /// Serialize this value into the given serializer.
13    fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
14    where
15        S: Serializer;
16}
17
18/// A structure that can serialize data into ruby marshal format.
19///
20/// You MUST provide exact sizes for arrays, hashes, etc because marshal prefixes them with their size.
21pub trait Serializer: Sized {
22    /// The output of the serializer.
23    type Ok;
24
25    /// The ivar serializer of this serializer.
26    type SerializeIvars: SerializeIvars<Ok = Self::Ok>;
27    /// The hash serializer of this serializer.
28    type SerializeHash: SerializeHash<Ok = Self::Ok>;
29    /// The array serializer of this serializer.
30    type SerializeArray: SerializeArray<Ok = Self::Ok>;
31
32    /// Serialize a nil value.
33    fn serialize_nil(self) -> Result<Self::Ok>;
34
35    /// Serialize a boolean value.
36    fn serialize_bool(self, v: bool) -> Result<Self::Ok>;
37
38    /// Serialize an integer value within the interval [-2<sup>30</sup>, 2<sup>30</sup>).
39    fn serialize_fixnum(self, v: Fixnum) -> Result<Self::Ok>;
40
41    /// Serialize an integer value outside of the interval [-2<sup>30</sup>, 2<sup>30</sup>).
42    fn serialize_bignum(self, v: BignumRef<'_>) -> Result<Self::Ok>;
43
44    /// Serialize a float value.
45    fn serialize_f64(self, v: f64) -> Result<Self::Ok>;
46
47    /// Serialize a hash.
48    fn serialize_hash(self, len: usize) -> Result<Self::SerializeHash>;
49
50    /// Serialize an array.
51    fn serialize_array(self, len: usize) -> Result<Self::SerializeArray>;
52
53    /// Serialize a string.
54    fn serialize_string(self, data: &[u8]) -> Result<Self::Ok>;
55
56    /// Serialize a symbol.
57    fn serialize_symbol(self, sym: &Sym) -> Result<Self::Ok>;
58
59    /// Serialize a regular expression.
60    fn serialize_regular_expression(self, regex: &[u8], flags: u8) -> Result<Self::Ok>;
61
62    /// Serialize a object.
63    fn serialize_object(self, class: &Sym, len: usize) -> Result<Self::SerializeIvars>;
64
65    /// Serialize a struct.
66    fn serialize_struct(self, name: &Sym, len: usize) -> Result<Self::SerializeIvars>;
67
68    /// Serialize a class.
69    fn serialize_class(self, class: &Sym) -> Result<Self::Ok>;
70
71    /// Serialize a module.
72    fn serialize_module(self, module: &Sym) -> Result<Self::Ok>;
73
74    /// Serialize an instance.
75    fn serialize_instance<V>(self, value: &V, len: usize) -> Result<Self::SerializeIvars>
76    where
77        V: Serialize + ?Sized;
78
79    /// Serialize an extended value.
80    fn serialize_extended<V>(self, module: &Sym, value: &V) -> Result<Self::Ok>
81    where
82        V: Serialize + ?Sized;
83
84    /// Serialize a user class.
85    fn serialize_user_class<V>(self, class: &Sym, value: &V) -> Result<Self::Ok>
86    where
87        V: Serialize + ?Sized;
88
89    /// Serialize user data.
90    fn serialize_user_data(self, class: &Sym, data: &[u8]) -> Result<Self::Ok>;
91
92    /// Serialize user marshal.
93    fn serialize_user_marshal<V>(self, class: &Sym, value: &V) -> Result<Self::Ok>
94    where
95        V: Serialize + ?Sized;
96
97    /// Serialize data.
98    fn serialize_data<V>(self, class: &Sym, value: &V) -> Result<Self::Ok>
99    where
100        V: Serialize + ?Sized;
101
102    /// A convenience method for serializing a string.
103    fn serialize_rust_string(self, string: &str) -> Result<Self::Ok> {
104        struct StringSerialize<'a>(&'a str);
105        impl Serialize for StringSerialize<'_> {
106            fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
107            where
108                S: Serializer,
109            {
110                serializer.serialize_string(self.0.as_bytes())
111            }
112        }
113        let mut fields = self.serialize_instance(&StringSerialize(string), 1)?;
114        fields.serialize_entry(Sym::new("E"), &true)?;
115        fields.end()
116    }
117
118    /// A convenience method for serializing an array.
119    fn collect_array<I>(self, iter: I) -> Result<Self::Ok>
120    where
121        I: IntoIterator,
122        I::IntoIter: ExactSizeIterator,
123        I::Item: Serialize,
124    {
125        let iter = iter.into_iter();
126        let mut serialize_array = self.serialize_array(iter.len())?;
127        for item in iter {
128            serialize_array.serialize_element(&item)?;
129        }
130        serialize_array.end()
131    }
132
133    /// A convenience method for serializing a hashmap.
134    fn collect_hash<K, V, I>(self, iter: I) -> Result<Self::Ok>
135    where
136        I: IntoIterator<Item = (K, V)>,
137        I::IntoIter: ExactSizeIterator,
138        K: Serialize,
139        V: Serialize,
140    {
141        let iter = iter.into_iter();
142        let mut serialize_hash = self.serialize_hash(iter.len())?;
143        for (key, value) in iter {
144            serialize_hash.serialize_entry(&key, &value)?;
145        }
146        serialize_hash.end()
147    }
148}
149
150/// A structure that can serialize instance variables of an object.
151pub trait SerializeIvars {
152    /// The output of the serializer.
153    type Ok;
154
155    /// Serialize a field.
156    ///
157    /// Generally you should have a symbol prefixed with an `@` character.
158    /// It's not invalid to not do this, but ruby will discard your data outside of a specific circumstance.
159    ///
160    /// When serializing a string, the ivar `E` will indicate the encoding of the string.
161    /// `false`: ASCII-8BIT
162    /// `true`: UTF-8
163    /// everything else: custom encoding
164    ///
165    /// Not providing an encoding will mean that ruby will assume the encoding is binary.
166    fn serialize_field(&mut self, k: &Sym) -> Result<()>;
167
168    /// Serialize a value.
169    ///
170    /// Must be called after `serialize_field`.
171    fn serialize_value<V>(&mut self, v: &V) -> Result<()>
172    where
173        V: Serialize + ?Sized;
174
175    /// Serialize a field and value.
176    fn serialize_entry<V>(&mut self, k: &Sym, v: &V) -> Result<()>
177    where
178        V: Serialize + ?Sized,
179    {
180        self.serialize_field(k)?;
181        self.serialize_value(v)
182    }
183
184    /// End the serialization.
185    fn end(self) -> Result<Self::Ok>;
186}
187
188/// A structure that can serialize a hash.
189pub trait SerializeHash {
190    /// The output of the serializer.
191    type Ok;
192
193    /// Serialize a key.
194    fn serialize_key<K>(&mut self, k: &K) -> Result<()>
195    where
196        K: Serialize + ?Sized;
197
198    /// Serialize a value.
199    ///
200    /// Must be called after `serialize_key`.
201    fn serialize_value<V>(&mut self, v: &V) -> Result<()>
202    where
203        V: Serialize + ?Sized;
204
205    /// Serialize a key and value.
206    fn serialize_entry<K, V>(&mut self, k: &K, v: &V) -> Result<()>
207    where
208        K: Serialize + ?Sized,
209        V: Serialize + ?Sized,
210    {
211        self.serialize_key(k)?;
212        self.serialize_value(v)
213    }
214
215    /// End the serialization.
216    fn end(self) -> Result<Self::Ok>;
217}
218
219/// A structure that can serialize an array.
220pub trait SerializeArray {
221    /// The output of the serializer.
222    type Ok;
223
224    /// Serialize an element.
225    fn serialize_element<T>(&mut self, v: &T) -> Result<()>
226    where
227        T: Serialize + ?Sized;
228
229    /// End the serialization.
230    fn end(self) -> Result<Self::Ok>;
231}