1use crate::consts::RESERVED_NOT_EMITTED_V01;
4use crate::envelope;
5use crate::error::{Error, Result};
6use crate::payload::Payload;
7use crate::tag::Tag;
8
9pub fn encode(tag: Tag, payload: &Payload) -> Result<String> {
17 if RESERVED_NOT_EMITTED_V01.contains(tag.as_bytes()) {
19 return Err(Error::ReservedTagNotEmittedInV01 {
20 got: *tag.as_bytes(),
21 });
22 }
23 payload.validate()?;
25 let c = envelope::package(tag, payload.as_bytes())?;
27 Ok(c.to_string())
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use crate::consts::VALID_STR_LENGTHS;
34
35 #[test]
36 fn encode_entr_all_lengths_succeed() {
37 for (i, len) in [16usize, 20, 24, 28, 32].iter().enumerate() {
38 let p = Payload::Entr(vec![0xAAu8; *len]);
39 let s = encode(Tag::ENTR, &p).unwrap();
40 assert_eq!(s.len(), VALID_STR_LENGTHS[i]);
41 assert!(s.starts_with("ms10entrs"), "got {}", s);
42 }
43 }
44
45 #[test]
46 fn encode_rejects_seed_tag() {
47 let p = Payload::Entr(vec![0u8; 16]);
48 let seed_tag = Tag::try_new("seed").unwrap();
49 assert!(matches!(
50 encode(seed_tag, &p),
51 Err(Error::ReservedTagNotEmittedInV01 { .. })
52 ));
53 }
54
55 #[test]
56 fn encode_rejects_xprv_tag() {
57 let p = Payload::Entr(vec![0u8; 16]);
58 let xprv_tag = Tag::try_new("xprv").unwrap();
59 assert!(matches!(
60 encode(xprv_tag, &p),
61 Err(Error::ReservedTagNotEmittedInV01 { .. })
62 ));
63 }
64
65 #[test]
66 fn encode_rejects_off_by_one_entr_length() {
67 let p = Payload::Entr(vec![0u8; 17]);
68 assert!(matches!(
69 encode(Tag::ENTR, &p),
70 Err(Error::PayloadLengthMismatch { .. })
71 ));
72 }
73}