1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
use crate::{
value::{Number, Precision, Timestamp},
ArrayWriter, DictWriter, Literal, Writer,
};
/// High-level encoding functions to write values in their canonical format.
///
/// ```
/// use cbor_data::{CborBuilder, Encoder, Writer};
///
/// let cbor = CborBuilder::default().encode_u64(12);
///
/// let array = CborBuilder::default().encode_array(|builder| {
/// builder
/// .encode_u64(18)
/// .encode_i64(-12);
/// });
///
/// let array2 = CborBuilder::default().with_max_definite_size(Some(1)).write_array(None, |builder| {
/// builder
/// .encode_u64(18)
/// .encode_i64(-12);
/// });
///
/// let dict = CborBuilder::default().encode_dict(|builder| {
/// builder
/// .with_key("a", |b| b.encode_u64(14))
/// .with_key("b", |b| b.encode_i64(-1));
/// });
///
/// let (dict2, ret) = CborBuilder::default().write_dict_ret(None, |builder| {
/// builder
/// .with_key("a", |b| b.encode_u64(14))
/// .with_key("b", |b| b.encode_i64(-1));
/// "hello"
/// });
/// assert_eq!(ret, "hello");
///
/// # assert_eq!(cbor.as_slice(), vec![0x0cu8]);
/// # assert_eq!(array.as_slice(), vec![0x82u8, 0x12, 0x2b]);
/// # assert_eq!(array2.as_slice(), vec![0x9fu8, 0x12, 0x2b, 0xff]);
/// # assert_eq!(dict.as_slice(), vec![0xa2u8, 0x61, b'a', 0x0e, 0x61, b'b', 0x20]);
/// # assert_eq!(dict2.as_slice(), vec![0xa2u8, 0x61, b'a', 0x0e, 0x61, b'b', 0x20]);
/// ```
pub trait Encoder: Writer {
fn encode_undefined(self) -> Self::Output {
self.write_undefined(None)
}
fn encode_null(self) -> Self::Output {
self.write_null(None)
}
fn encode_bool(self, value: bool) -> Self::Output {
self.write_bool(value, None)
}
/// Encode an unsigned integer of at most 64 bit.
///
/// Also to be used for smaller unsigned integers:
///
/// ```
/// use cbor_data::{CborBuilder, Encoder};
///
/// let short = 12345u16;
/// let cbor = CborBuilder::default().encode_u64(short.into());
///
/// # assert_eq!(cbor.as_slice(), vec![0x19u8, 48, 57]);
/// ```
fn encode_u64(self, value: u64) -> Self::Output {
self.write_pos(value, None)
}
/// Encode a signed integer of at most 64 bit.
///
/// Also to be used for smaller signed integers:
///
/// ```
/// use cbor_data::{CborBuilder, Encoder};
///
/// let short = -12345i16;
/// let cbor = CborBuilder::default().encode_i64(short.into());
///
/// # assert_eq!(cbor.as_slice(), vec![0x39u8, 48, 56]);
/// ```
fn encode_i64(self, value: i64) -> Self::Output {
if value < 0 {
self.write_neg((-1 - value) as u64, None)
} else {
self.write_pos(value as u64, None)
}
}
/// Encode a floating-point number of at most 64 bit.
///
/// Also to be used for smaller formats:
///
/// ```
/// use cbor_data::{CborBuilder, Encoder};
///
/// let single = -3.14f32;
/// let cbor = CborBuilder::default().encode_f64(single.into());
///
/// # assert_eq!(cbor.as_slice(), vec![0xfbu8, 192, 9, 30, 184, 96, 0, 0, 0]);
/// ```
fn encode_f64(self, value: f64) -> Self::Output {
self.write_lit(Literal::L8(value.to_bits()), None)
}
/// Encode a timestamp with given target precision
///
/// Since the CBOR-encoding itself does not carry precision information, the result
/// is not guaranteed to round-trip as the exact same timestamp. Encoding with `Precision::Seconds`
/// will discard the `nanos()` part.
///
/// If the `rfc3339` feature flag is enabled, textual representation is chosen for
/// subsecond precision when encoding as a double-precision floating-point number would
/// not be enough (float is sufficient for 285 years around 1970 at microsecond precision).
/// Textual representation retains timezone information in the output.
fn encode_timestamp(self, timestamp: Timestamp, precision: Precision) -> Self::Output {
timestamp.encode(self, precision)
}
/// Encode a possibly big number
///
/// The number will be encoded as simple integer or float if its mantissa is small enough.
fn encode_number(self, number: &Number) -> Self::Output {
number.encode(self)
}
/// Encode a string.
///
/// ```
/// use cbor_data::{CborBuilder, Encoder};
///
/// let cbor = CborBuilder::default().encode_array(|builder| {
/// builder.encode_str("hello");
/// builder.encode_str(String::new());
/// });
///
/// # assert_eq!(cbor.as_slice(), vec![0x82, 0x65, b'h', b'e', b'l', b'l', b'o', 0x60]);
/// ```
fn encode_str(self, value: impl AsRef<str>) -> Self::Output {
self.write_str(value.as_ref(), None)
}
/// Encode a byte string.
///
/// ```
/// use cbor_data::{CborBuilder, Encoder};
///
/// let cbor = CborBuilder::default().encode_array(|builder| {
/// builder.encode_bytes(b"hello");
/// });
///
/// # assert_eq!(cbor.as_slice(), vec![0x81, 0x45, b'h', b'e', b'l', b'l', b'o']);
/// ```
fn encode_bytes(self, value: impl AsRef<[u8]>) -> Self::Output {
self.write_bytes(value.as_ref(), None)
}
/// Write an array that is then filled by the provided closure using the passed builder.
///
/// see [`trait Encoder`](trait.Encoder.html) for usage examples
fn encode_array<F>(self, f: F) -> Self::Output
where
F: FnOnce(&mut ArrayWriter<'_>),
{
self.write_array(None, |builder| f(builder))
}
/// Write a dict that is then filled by the provided closure using the passed builder.
///
/// see [`trait Encoder`](trait.Encoder.html) for usage examples
fn encode_dict<F>(self, f: F) -> Self::Output
where
F: FnOnce(&mut DictWriter<'_>),
{
self.write_dict(None, |builder| f(builder))
}
}
impl<T: Writer> Encoder for T {}