Add 'allow_extra_keys' parameter to dict_of() and dict_of_opt()

This commit is contained in:
Alex 2022-11-17 15:06:42 +01:00
parent e1b6514f24
commit c6e7a42b7e
Signed by: lx
GPG key ID: 0E496D15096376BE

View file

@ -262,14 +262,17 @@ impl<'a, 'b> Term<'a, 'b> {
/// ``` /// ```
/// use nettext::dec::decode; /// use nettext::dec::decode;
/// ///
/// let term = decode(b"{ k1 = v1, k2 = v2 }").unwrap(); /// let term = decode(b"{ k1 = v1, k2 = v2, k3 = v3 }").unwrap();
/// let [s1, s2] = term.dict_of([b"k1", b"k2"]).unwrap(); /// let [s1, s2] = term.dict_of([b"k1", b"k2"], true).unwrap();
/// assert_eq!(s1.str().unwrap(), b"v1"); /// assert_eq!(s1.str().unwrap(), b"v1");
/// assert_eq!(s2.str().unwrap(), b"v2"); /// assert_eq!(s2.str().unwrap(), b"v2");
///
/// assert!(term.dict_of([b"k1", b"k2"], false).is_err());
/// ``` /// ```
pub fn dict_of<const N: usize>( pub fn dict_of<const N: usize>(
&self, &self,
keys: [&'static [u8]; N], keys: [&'static [u8]; N],
allow_extra_keys: bool,
) -> Result<[Term<'a, '_>; N], TypeError> { ) -> Result<[Term<'a, '_>; N], TypeError> {
match self.0.mkref() { match self.0.mkref() {
AnyTerm::DictRef(_, dict) => { AnyTerm::DictRef(_, dict) => {
@ -279,12 +282,14 @@ impl<'a, 'b> Term<'a, 'b> {
return Err(TypeError::MissingKey(debug(k).to_string())); return Err(TypeError::MissingKey(debug(k).to_string()));
} }
} }
if !allow_extra_keys {
// Check that dictionnary contains no extraneous keys // Check that dictionnary contains no extraneous keys
for k in dict.keys() { for k in dict.keys() {
if !keys.contains(k) { if !keys.contains(k) {
return Err(TypeError::UnexpectedKey(debug(k).to_string())); return Err(TypeError::UnexpectedKey(debug(k).to_string()));
} }
} }
}
Ok(keys.map(|k| Term(dict.get(k).unwrap().mkref()))) Ok(keys.map(|k| Term(dict.get(k).unwrap().mkref())))
} }
_ => Err(TypeError::WrongType("DICT")), _ => Err(TypeError::WrongType("DICT")),
@ -299,24 +304,29 @@ impl<'a, 'b> Term<'a, 'b> {
/// ``` /// ```
/// use nettext::dec::decode; /// use nettext::dec::decode;
/// ///
/// let term = decode(b"{ k1 = v1, k2 = v2 }").unwrap(); /// let term = decode(b"{ k1 = v1, k2 = v2, k4 = v4 }").unwrap();
/// let [s1, s2, s3] = term.dict_of_opt([b"k1", b"k2", b"k3"]).unwrap(); /// let [s1, s2, s3] = term.dict_of_opt([b"k1", b"k2", b"k3"], true).unwrap();
/// assert_eq!(s1.unwrap().str().unwrap(), b"v1"); /// assert_eq!(s1.unwrap().str().unwrap(), b"v1");
/// assert_eq!(s2.unwrap().str().unwrap(), b"v2"); /// assert_eq!(s2.unwrap().str().unwrap(), b"v2");
/// assert!(s3.is_none()); /// assert!(s3.is_none());
///
/// assert!(term.dict_of_opt([b"k1", b"k2", b"k3"], false).is_err());
/// ``` /// ```
pub fn dict_of_opt<const N: usize>( pub fn dict_of_opt<const N: usize>(
&self, &self,
keys: [&'static [u8]; N], keys: [&'static [u8]; N],
allow_extra_keys: bool,
) -> Result<[Option<Term<'a, '_>>; N], TypeError> { ) -> Result<[Option<Term<'a, '_>>; N], TypeError> {
match self.0.mkref() { match self.0.mkref() {
AnyTerm::DictRef(_, dict) => { AnyTerm::DictRef(_, dict) => {
if !allow_extra_keys {
// Check that dictionnary contains no extraneous keys // Check that dictionnary contains no extraneous keys
for k in dict.keys() { for k in dict.keys() {
if !keys.contains(k) { if !keys.contains(k) {
return Err(TypeError::UnexpectedKey(debug(k).to_string())); return Err(TypeError::UnexpectedKey(debug(k).to_string()));
} }
} }
}
Ok(keys.map(|k| dict.get(k).map(|x| Term(x.mkref())))) Ok(keys.map(|k| dict.get(k).map(|x| Term(x.mkref()))))
} }
_ => Err(TypeError::WrongType("DICT")), _ => Err(TypeError::WrongType("DICT")),