image4/payload/
owned.rs

1use super::{ComprInfo, PayloadProps, PayloadRef};
2use crate::Tag;
3use alloc::vec::Vec;
4use der::{
5    asn1::{Ia5String, OctetString},
6    referenced::{OwnedToRef, RefToOwned},
7    Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Writer,
8};
9
10/// An Image4 payload that owns its data.
11#[derive(Clone, Debug)]
12#[cfg_attr(test, derive(Eq, PartialEq))]
13pub struct Payload {
14    pub(super) tag_4cc: Tag,
15    pub(super) builder_string: Ia5String,
16    pub(super) data: OctetString,
17    pub(super) keybags: Option<OctetString>,
18    pub(super) compr_info: Option<ComprInfo>,
19    pub(super) props: Option<PayloadProps>,
20}
21
22impl<'a> Payload {
23    /// Creates a new payload from a tag, builder string and its contents.
24    pub fn new(tag: Tag, builder_string: &str, data: Vec<u8>) -> der::Result<Self> {
25        Ok(Self {
26            tag_4cc: tag,
27            builder_string: Ia5String::new(builder_string)?,
28            data: OctetString::new(data)?,
29            keybags: None,
30            compr_info: None,
31            props: None,
32        })
33    }
34
35    /// Parses a DER-encoded payload into a [`Payload`].
36    pub fn parse(bytes: &'a [u8]) -> der::Result<Self> {
37        Self::from_der(bytes)
38    }
39
40    /// Returns the 4CC tag of the payload.
41    pub fn tag(&self) -> Tag {
42        self.tag_4cc
43    }
44
45    /// Sets the 4CC tag of the payload.
46    pub fn set_tag(&mut self, tag: Tag) {
47        self.tag_4cc = tag;
48    }
49
50    /// Returns the string identifying the program used to build the payload.
51    pub fn builder_string(&self) -> &str {
52        self.builder_string.as_str()
53    }
54
55    /// Sets the string identifying the program used to build the payload.
56    ///
57    /// # Panics
58    /// This function will panic in case either the string contains characters that do not belong
59    /// to the IA5 alphabet (ASCII characters larger than 127) or the length of the string is larger
60    /// than the maximum length supported by the [`der`] crate ([`Length::MAX`]).
61    pub fn set_builder_string(&mut self, s: &'a str) -> der::Result<()> {
62        self.builder_string = Ia5String::new(s)?;
63        Ok(())
64    }
65
66    /// Returns a reference to the payload's data.
67    pub fn data(&self) -> &[u8] {
68        self.data.as_bytes()
69    }
70
71    /// Sets the payload's data.
72    ///
73    /// # Panics
74    /// This function will panic in case the length of the data is larger than the maximum length
75    /// supported by the [`der`] crate ([`Length::MAX`]).
76    pub fn set_data(&mut self, data: Vec<u8>) -> der::Result<()> {
77        self.data = OctetString::new(data)?;
78        Ok(())
79    }
80
81    /// Returns a reference to the payload's encoded keybags if present.
82    pub fn keybags(&self) -> Option<&[u8]> {
83        self.keybags.as_ref().map(OctetString::as_bytes)
84    }
85
86    /// Sets new encoded keybags for the payload.
87    pub fn set_keybags(&mut self, bytes: Option<Vec<u8>>) -> der::Result<()> {
88        self.keybags = bytes.map(OctetString::new).transpose()?;
89        Ok(())
90    }
91
92    /// Returns a reference to the payload's compression info if present.
93    pub fn compr_info(&self) -> Option<&ComprInfo> {
94        self.compr_info.as_ref()
95    }
96
97    /// Sets new compression info for the payload.
98    pub fn set_compr_info(&mut self, compr_info: Option<ComprInfo>) {
99        self.compr_info = compr_info;
100    }
101
102    /// Returns a reference to the payload's properties if present.
103    pub fn props(&self) -> Option<&PayloadProps> {
104        self.props.as_ref()
105    }
106
107    /// Sets new properties for the payload.
108    pub fn set_props(&mut self, props: Option<PayloadProps>) {
109        self.props = props;
110    }
111
112    /// Decodes the part of an image payload after the magic string.
113    ///
114    /// May be used when it is required to first identify what kind of buffer you're looking at by
115    /// checking the magic string.
116    pub fn decode_after_magic<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
117        PayloadRef::decode_after_magic(decoder).map(Payload::from)
118    }
119}
120
121impl From<PayloadRef<'_>> for Payload {
122    fn from(value: PayloadRef<'_>) -> Self {
123        (&value).into()
124    }
125}
126
127impl From<&'_ PayloadRef<'_>> for Payload {
128    fn from(value: &'_ PayloadRef<'_>) -> Self {
129        Self {
130            tag_4cc: value.tag_4cc,
131            builder_string: value.builder_string.ref_to_owned(),
132            data: value.data.ref_to_owned(),
133            keybags: value.keybags.ref_to_owned(),
134            compr_info: value.compr_info.clone(),
135            props: value.props.ref_to_owned(),
136        }
137    }
138}
139
140impl OwnedToRef for Payload {
141    type Borrowed<'a> = PayloadRef<'a>;
142
143    fn owned_to_ref(&self) -> Self::Borrowed<'_> {
144        self.into()
145    }
146}
147
148impl<'a> DecodeValue<'a> for Payload {
149    fn decode_value<R: Reader<'a>>(decoder: &mut R, header: Header) -> der::Result<Self> {
150        PayloadRef::decode_value(decoder, header).map(Payload::from)
151    }
152}
153
154impl EncodeValue for Payload {
155    fn value_len(&self) -> der::Result<Length> {
156        PayloadRef::from(self).encoded_len()
157    }
158
159    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
160        PayloadRef::from(self).encode_value(encoder)
161    }
162}
163
164impl FixedTag for Payload {
165    const TAG: der::Tag = der::Tag::Sequence;
166}