ldap3_serde/controls_impl/
read_entry.rs

1use std::collections::HashMap;
2
3use bytes::BytesMut;
4
5use super::{ControlParser, MakeCritical, RawControl};
6use crate::search::{ResultEntry, SearchEntry};
7use lber_serde::parse::parse_tag;
8use lber_serde::structures::{ASNTag, OctetString, Sequence, Tag};
9use lber_serde::write;
10
11pub const PRE_READ_OID: &str = "1.3.6.1.1.13.1";
12pub const POST_READ_OID: &str = "1.3.6.1.1.13.2";
13
14#[derive(Debug)]
15struct ReadEntry<S> {
16    attrs: Vec<S>,
17    oid: &'static str,
18}
19
20/// Response for Pre-Read and Post-Read controls.
21///
22/// The structure is the same for both cases, but type aliases are provided
23/// for uniformity.
24#[derive(Debug)]
25pub struct ReadEntryResp {
26    /// Attributes.
27    pub attrs: HashMap<String, Vec<String>>,
28    /// Binary-valued attributes.
29    pub bin_attrs: HashMap<String, Vec<Vec<u8>>>,
30}
31
32/// Type alias for Pre-Read response.
33pub type PreReadResp = ReadEntryResp;
34
35/// Type alias for Post-Read response.
36pub type PostReadResp = ReadEntryResp;
37
38/// Pre-Read request control ([RFC 4527](https://tools.ietf.org/html/rfc4527)).
39pub struct PreRead<S>(ReadEntry<S>);
40
41impl<S: AsRef<str>> PreRead<S> {
42    /// Create a new control instance with the specified list of attribute names/OIDs.
43    #[allow(clippy::new_ret_no_self)]
44    pub fn new(attrs: Vec<S>) -> RawControl {
45        PreRead(ReadEntry {
46            attrs,
47            oid: PRE_READ_OID,
48        })
49        .into()
50    }
51}
52
53impl<S> MakeCritical for PreRead<S> {}
54
55impl<S: AsRef<str>> From<PreRead<S>> for RawControl {
56    fn from(pr: PreRead<S>) -> RawControl {
57        from_read_entry(pr.0)
58    }
59}
60
61/// Post-Read request control ([RFC 4527](https://tools.ietf.org/html/rfc4527)).
62pub struct PostRead<S>(ReadEntry<S>);
63
64impl<S> MakeCritical for PostRead<S> {}
65
66impl<S: AsRef<str>> PostRead<S> {
67    /// Create a new control instance with the specified list of attribute names/OIDs.
68    #[allow(clippy::new_ret_no_self)]
69    pub fn new(attrs: Vec<S>) -> RawControl {
70        PostRead(ReadEntry {
71            attrs,
72            oid: POST_READ_OID,
73        })
74        .into()
75    }
76}
77
78impl<S: AsRef<str>> From<PostRead<S>> for RawControl {
79    fn from(pr: PostRead<S>) -> RawControl {
80        from_read_entry(pr.0)
81    }
82}
83
84fn from_read_entry<S: AsRef<str>>(re: ReadEntry<S>) -> RawControl {
85    let mut attr_vec = Vec::new();
86    let mut enc_size_est = 2;
87    for attr in re.attrs {
88        enc_size_est += attr.as_ref().len() + 2;
89        let tag = Tag::OctetString(OctetString {
90            inner: Vec::from(attr.as_ref()),
91            ..Default::default()
92        });
93        attr_vec.push(tag);
94    }
95    let cval = Tag::Sequence(Sequence {
96        inner: attr_vec,
97        ..Default::default()
98    })
99    .into_structure();
100    let mut buf = BytesMut::with_capacity(enc_size_est);
101    write::encode_into(&mut buf, cval).expect("encoded");
102    RawControl {
103        ctype: re.oid.to_owned(),
104        crit: false,
105        val: Some(Vec::from(&buf[..])),
106    }
107}
108
109impl ControlParser for ReadEntryResp {
110    fn parse(val: &[u8]) -> ReadEntryResp {
111        let tag = match parse_tag(val) {
112            Ok((_, tag)) => tag,
113            _ => panic!("failed to parse pre-read attribute values"),
114        };
115        let se = SearchEntry::construct(ResultEntry::new(tag));
116        ReadEntryResp {
117            attrs: se.attrs,
118            bin_attrs: se.bin_attrs,
119        }
120    }
121}