msgpack/
pack.rs

1mod int;
2mod primitive;
3mod timestamp;
4mod uint;
5mod value;
6
7use crate::{code, PackError};
8use primitive::*;
9use std::io;
10
11pub use int::*;
12pub use primitive::write_all;
13pub use timestamp::*;
14pub use uint::*;
15pub use value::pack_value;
16
17pub fn pack_f32<W: io::Write>(writer: &mut W, v: f32) -> Result<(), PackError> {
18    write_data_u8(writer, code::FLOAT32)?;
19    write_data_f32(writer, v)
20}
21
22pub fn pack_f64<W: io::Write>(writer: &mut W, v: f64) -> Result<(), PackError> {
23    write_data_u8(writer, code::FLOAT64)?;
24    write_data_f64(writer, v)
25}
26
27pub fn pack_bool<W: io::Write>(writer: &mut W, v: bool) -> Result<(), PackError> {
28    write_data_u8(writer, if v { code::TRUE } else { code::FALSE })
29}
30
31pub fn pack_nil<W: io::Write>(writer: &mut W) -> Result<(), PackError> {
32    write_data_u8(writer, code::NIL)
33}
34
35const FIXSTR_LIMIT: usize = 1 << 5;
36const STR8_LIMIT: usize = 1 << 8;
37const STR16_LIMIT: usize = 1 << 16;
38const STR32_LIMIT: usize = 1 << 32;
39
40pub fn pack_str<W: io::Write>(writer: &mut W, v: &str) -> Result<(), PackError> {
41    let len = v.len();
42    if len < FIXSTR_LIMIT {
43        write_data_u8(writer, code::FIX_STR | len as u8)?;
44        write_all(writer, v[..len].as_bytes())
45    } else if len < STR8_LIMIT {
46        write_data_u8(writer, code::STR8)?;
47        write_data_u8(writer, len as u8)?;
48        write_all(writer, v[..len].as_bytes())
49    } else if len < STR16_LIMIT {
50        write_data_u8(writer, code::STR16)?;
51        write_data_u16(writer, len as u16)?;
52        write_all(writer, v[..len].as_bytes())
53    } else if len < STR32_LIMIT {
54        write_data_u8(writer, code::STR32)?;
55        write_data_u32(writer, len as u32)?;
56        write_all(writer, v[..len].as_bytes())
57    } else {
58        unreachable!()
59    }
60}
61
62// for string contains invalid byte sequence.
63pub fn pack_str_from_slice<W: io::Write>(writer: &mut W, v: &[u8]) -> Result<(), PackError> {
64    let len = v.len();
65    if len < FIXSTR_LIMIT {
66        write_data_u8(writer, code::FIX_STR | len as u8)?;
67        write_all(writer, &v[..len])
68    } else if len < STR8_LIMIT {
69        write_data_u8(writer, code::STR8)?;
70        write_data_u8(writer, len as u8)?;
71        write_all(writer, &v[..len])
72    } else if len < STR16_LIMIT {
73        write_data_u8(writer, code::STR16)?;
74        write_data_u16(writer, len as u16)?;
75        write_all(writer, &v[..len])
76    } else if len < STR32_LIMIT {
77        write_data_u8(writer, code::STR32)?;
78        write_data_u32(writer, len as u32)?;
79        write_all(writer, &v[..len])
80    } else {
81        unreachable!()
82    }
83}
84
85const BIN8_LIMIT: usize = 1 << 8;
86const BIN16_LIMIT: usize = 1 << 16;
87const BIN32_LIMIT: usize = 1 << 32;
88
89pub fn pack_bin<W: io::Write>(writer: &mut W, v: &[u8]) -> Result<(), PackError> {
90    let len = v.len();
91    if len < BIN8_LIMIT {
92        write_data_u8(writer, code::BIN8)?;
93        write_data_u8(writer, len as u8)?;
94        write_all(writer, &v[..len])
95    } else if len < BIN16_LIMIT {
96        write_data_u8(writer, code::BIN16)?;
97        write_data_u16(writer, len as u16)?;
98        write_all(writer, &v[..len])
99    } else if len < BIN32_LIMIT {
100        write_data_u8(writer, code::BIN32)?;
101        write_data_u32(writer, len as u32)?;
102        write_all(writer, &v[..len])
103    } else {
104        unreachable!()
105    }
106}
107
108const FIXARRAY_LIMIT: usize = 1 << 4;
109const ARRAY16_LIMIT: usize = 1 << 16;
110const ARRAY32_LIMIT: usize = 1 << 32;
111
112pub fn pack_ary_header<W: io::Write>(writer: &mut W, len: usize) -> Result<(), PackError> {
113    if len < FIXARRAY_LIMIT {
114        write_data_u8(writer, code::FIX_ARRAY | (len as u8))
115    } else if len < ARRAY16_LIMIT {
116        write_data_u8(writer, code::ARRAY16)?;
117        write_data_u16(writer, len as u16)
118    } else if len < ARRAY32_LIMIT {
119        write_data_u8(writer, code::ARRAY32)?;
120        write_data_u32(writer, len as u32)
121    } else {
122        unreachable!()
123    }
124}
125
126const FIXMAP_LIMIT: usize = 1 << 4;
127const MAP16_LIMIT: usize = 1 << 16;
128const MAP32_LIMIT: usize = 1 << 32;
129
130pub fn pack_map_header<W: io::Write>(writer: &mut W, len: usize) -> Result<(), PackError> {
131    if len < FIXMAP_LIMIT {
132        write_data_u8(writer, code::FIX_MAP | (len as u8))
133    } else if len < MAP16_LIMIT {
134        write_data_u8(writer, code::MAP16)?;
135        write_data_u16(writer, len as u16)
136    } else if len < MAP32_LIMIT {
137        write_data_u8(writer, code::MAP32)?;
138        write_data_u32(writer, len as u32)
139    } else {
140        unreachable!()
141    }
142}
143
144pub fn pack_ext_header<W: io::Write>(
145    writer: &mut W,
146    ext_type: i8,
147    len: usize,
148) -> Result<(), PackError> {
149    use std::io::ErrorKind;
150    if ext_type < 0 {
151        return Err(PackError::WriteError(io::Error::new(
152            ErrorKind::Other,
153            "type < 0 is reserved for future extension",
154        )));
155    }
156    match len {
157        1 => write_data_u8(writer, code::FIXEXT1)?,
158        2 => write_data_u8(writer, code::FIXEXT2)?,
159        4 => write_data_u8(writer, code::FIXEXT4)?,
160        8 => write_data_u8(writer, code::FIXEXT8)?,
161        16 => write_data_u8(writer, code::FIXEXT16)?,
162        17..=256 => {
163            write_data_u8(writer, code::EXT8)?;
164            write_data_u8(writer, len as u8)?
165        }
166        256..=65536 => {
167            write_data_u8(writer, code::EXT16)?;
168            write_data_u16(writer, len as u16)?
169        }
170        _ => {
171            write_data_u8(writer, code::EXT32)?;
172            write_data_u32(writer, len as u32)?
173        }
174    };
175
176    write_data_i8(writer, ext_type)
177}