matrix_pickle/
encode.rs

1// Copyright 2022 Damir Jelić
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::io::{Cursor, Write};
16
17use crate::{EncodeError, MAX_ARRAY_LENGTH};
18
19/// A trait for encoding values into the `matrix-pickle` binary format.
20pub trait Encode {
21    /// Try to encode and write a value to the given writer, returning how many bytes were written.
22    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError>;
23
24    /// Try to encode a value into a new `Vec`.
25    fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> {
26        let buffer = Vec::new();
27        let mut cursor = Cursor::new(buffer);
28
29        self.encode(&mut cursor)?;
30
31        Ok(cursor.into_inner())
32    }
33}
34
35impl Encode for u8 {
36    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
37        Ok(writer.write(&[*self])?)
38    }
39}
40
41impl Encode for bool {
42    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
43        (*self as u8).encode(writer)
44    }
45}
46
47impl<const N: usize> Encode for [u8; N] {
48    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
49        writer.write_all(self)?;
50
51        Ok(N)
52    }
53}
54
55impl Encode for u32 {
56    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
57        let bytes = self.to_be_bytes();
58        bytes.encode(writer)
59    }
60}
61
62impl Encode for usize {
63    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
64        let value = u32::try_from(*self).map_err(|_| EncodeError::OutsideU32Range(*self))?;
65
66        value.encode(writer)
67    }
68}
69
70impl<T: Encode> Encode for [T] {
71    fn encode(&self, writer: &mut impl Write) -> Result<usize, EncodeError> {
72        let length = self.len();
73
74        if length > MAX_ARRAY_LENGTH {
75            Err(EncodeError::ArrayTooBig(length))
76        } else {
77            let mut ret = length.encode(writer)?;
78
79            for value in self {
80                ret += value.encode(writer)?;
81            }
82
83            Ok(ret)
84        }
85    }
86}