1#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct LdapAttributeResultValues {
8 pub entry_dn: String,
10 pub attribute_name: String,
12 pub string_values: Vec<String>,
14 pub binary_values: Vec<Vec<u8>>,
16}
17
18#[cfg(feature = "ldap3")]
21pub trait SearchEntryExt {
22 fn attribute_results(&self, attribute_name: &str) -> LdapAttributeResultValues;
24}
25
26#[cfg(feature = "ldap3")]
27impl SearchEntryExt for ldap3::SearchEntry {
28 fn attribute_results(&self, attribute_name: &str) -> LdapAttributeResultValues {
29 let string_values = self.attrs.get(attribute_name);
30 let binary_values = self.bin_attrs.get(attribute_name);
31 LdapAttributeResultValues {
32 entry_dn: self.dn.to_owned(),
33 attribute_name: attribute_name.to_owned(),
34 string_values: string_values.map_or(Vec::new(), |v| v.to_vec()),
35 binary_values: binary_values.map_or(Vec::new(), |v| v.to_vec()),
36 }
37 }
38}
39
40pub trait FromStringLdapType {
43 type Error;
45
46 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
52 where
53 Self: Sized;
54}
55
56impl FromStringLdapType for String {
57 type Error = std::convert::Infallible;
58
59 fn parse(_entry_dn: &str, _attribute_name: &str, value: String) -> Result<Self, Self::Error>
60 where
61 Self: Sized,
62 {
63 Ok(value)
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct UnexpectedStringValue {
71 source_entry_dn: String,
73 source_attribute_name: String,
75 conversion_target_name: String,
77 unexpected_value: String,
79}
80
81impl std::fmt::Display for UnexpectedStringValue {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(
84 f,
85 "Unexpected value in conversion of {} attribute {} to {}: {}",
86 self.source_entry_dn,
87 self.source_attribute_name,
88 self.conversion_target_name,
89 self.unexpected_value,
90 )
91 }
92}
93
94impl std::error::Error for UnexpectedStringValue {}
95
96impl FromStringLdapType for bool {
97 type Error = UnexpectedStringValue;
98
99 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
100 where
101 Self: Sized,
102 {
103 match std::ops::Deref::deref(&value) {
104 "TRUE" => Ok(true),
105 "FALSE" => Ok(false),
106 v => Err(UnexpectedStringValue {
107 source_entry_dn: entry_dn.to_owned(),
108 source_attribute_name: attribute_name.to_owned(),
109 conversion_target_name: "bool".to_string(),
110 unexpected_value: v.to_owned(),
111 }),
112 }
113 }
114}
115
116impl FromStringLdapType for u8 {
117 type Error = UnexpectedStringValue;
118
119 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
120 where
121 Self: Sized,
122 {
123 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
124 source_entry_dn: entry_dn.to_owned(),
125 source_attribute_name: attribute_name.to_owned(),
126 conversion_target_name: "u8".to_string(),
127 unexpected_value: value,
128 })
129 }
130}
131
132impl FromStringLdapType for i8 {
133 type Error = UnexpectedStringValue;
134
135 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
136 where
137 Self: Sized,
138 {
139 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
140 source_entry_dn: entry_dn.to_owned(),
141 source_attribute_name: attribute_name.to_owned(),
142 conversion_target_name: "i8".to_string(),
143 unexpected_value: value,
144 })
145 }
146}
147
148impl FromStringLdapType for u16 {
149 type Error = UnexpectedStringValue;
150
151 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
152 where
153 Self: Sized,
154 {
155 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
156 source_entry_dn: entry_dn.to_owned(),
157 source_attribute_name: attribute_name.to_owned(),
158 conversion_target_name: "u16".to_string(),
159 unexpected_value: value,
160 })
161 }
162}
163
164impl FromStringLdapType for i16 {
165 type Error = UnexpectedStringValue;
166
167 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
168 where
169 Self: Sized,
170 {
171 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
172 source_entry_dn: entry_dn.to_owned(),
173 source_attribute_name: attribute_name.to_owned(),
174 conversion_target_name: "i16".to_string(),
175 unexpected_value: value,
176 })
177 }
178}
179
180impl FromStringLdapType for u32 {
181 type Error = UnexpectedStringValue;
182
183 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
184 where
185 Self: Sized,
186 {
187 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
188 source_entry_dn: entry_dn.to_owned(),
189 source_attribute_name: attribute_name.to_owned(),
190 conversion_target_name: "u32".to_string(),
191 unexpected_value: value,
192 })
193 }
194}
195
196impl FromStringLdapType for i32 {
197 type Error = UnexpectedStringValue;
198
199 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
200 where
201 Self: Sized,
202 {
203 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
204 source_entry_dn: entry_dn.to_owned(),
205 source_attribute_name: attribute_name.to_owned(),
206 conversion_target_name: "i32".to_string(),
207 unexpected_value: value,
208 })
209 }
210}
211
212impl FromStringLdapType for u64 {
213 type Error = UnexpectedStringValue;
214
215 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
216 where
217 Self: Sized,
218 {
219 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
220 source_entry_dn: entry_dn.to_owned(),
221 source_attribute_name: attribute_name.to_owned(),
222 conversion_target_name: "u64".to_string(),
223 unexpected_value: value,
224 })
225 }
226}
227
228impl FromStringLdapType for i64 {
229 type Error = UnexpectedStringValue;
230
231 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
232 where
233 Self: Sized,
234 {
235 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
236 source_entry_dn: entry_dn.to_owned(),
237 source_attribute_name: attribute_name.to_owned(),
238 conversion_target_name: "i64".to_string(),
239 unexpected_value: value,
240 })
241 }
242}
243
244impl FromStringLdapType for u128 {
245 type Error = UnexpectedStringValue;
246
247 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
248 where
249 Self: Sized,
250 {
251 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
252 source_entry_dn: entry_dn.to_owned(),
253 source_attribute_name: attribute_name.to_owned(),
254 conversion_target_name: "u128".to_string(),
255 unexpected_value: value,
256 })
257 }
258}
259
260impl FromStringLdapType for i128 {
261 type Error = UnexpectedStringValue;
262
263 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
264 where
265 Self: Sized,
266 {
267 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
268 source_entry_dn: entry_dn.to_owned(),
269 source_attribute_name: attribute_name.to_owned(),
270 conversion_target_name: "i128".to_string(),
271 unexpected_value: value,
272 })
273 }
274}
275
276impl FromStringLdapType for usize {
277 type Error = UnexpectedStringValue;
278
279 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
280 where
281 Self: Sized,
282 {
283 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
284 source_entry_dn: entry_dn.to_owned(),
285 source_attribute_name: attribute_name.to_owned(),
286 conversion_target_name: "usize".to_string(),
287 unexpected_value: value,
288 })
289 }
290}
291
292impl FromStringLdapType for isize {
293 type Error = UnexpectedStringValue;
294
295 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
296 where
297 Self: Sized,
298 {
299 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
300 source_entry_dn: entry_dn.to_owned(),
301 source_attribute_name: attribute_name.to_owned(),
302 conversion_target_name: "isize".to_string(),
303 unexpected_value: value,
304 })
305 }
306}
307
308#[cfg(feature = "chumsky")]
309impl FromStringLdapType for crate::basic::DistinguishedName {
310 type Error = UnexpectedStringValue;
311
312 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
313 where
314 Self: Sized,
315 {
316 <Self as std::str::FromStr>::from_str(&value).map_err(|_err| UnexpectedStringValue {
317 source_entry_dn: entry_dn.to_owned(),
318 source_attribute_name: attribute_name.to_owned(),
319 conversion_target_name: "DistinguishedName".to_string(),
320 unexpected_value: value,
321 })
322 }
323}
324
325impl FromStringLdapType for oid::ObjectIdentifier {
326 type Error = UnexpectedStringValue;
327
328 fn parse(entry_dn: &str, attribute_name: &str, value: String) -> Result<Self, Self::Error>
329 where
330 Self: Sized,
331 {
332 <Self as TryFrom<&str>>::try_from(&value).map_err(|_err| UnexpectedStringValue {
333 source_entry_dn: entry_dn.to_owned(),
334 source_attribute_name: attribute_name.to_owned(),
335 conversion_target_name: "ObjectIdentifier".to_string(),
336 unexpected_value: value,
337 })
338 }
339}
340
341pub trait FromLdapType {
345 type Error;
347
348 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
356 where
357 Self: Sized;
358}
359
360#[derive(Debug, Clone)]
363pub enum VecOfFromStringLdapTypeError<E> {
364 LdapShouldNotReturnBinaryResult {
367 entry_dn: String,
369 attribute_name: String,
371 },
372 PrimitiveValueConversionError(E),
374}
375
376impl<E> std::fmt::Display for VecOfFromStringLdapTypeError<E>
377where
378 E: std::error::Error,
379{
380 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
381 match self {
382 Self::LdapShouldNotReturnBinaryResult {
383 entry_dn,
384 attribute_name,
385 } => {
386 write!(
387 f,
388 "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting a Vec of a type that only supports String inputs"
389 )
390 }
391 Self::PrimitiveValueConversionError(err) => {
392 write!(
393 f,
394 "encountered error converting a primitive value from String: {err}",
395 )
396 }
397 }
398 }
399}
400
401impl<E> std::error::Error for VecOfFromStringLdapTypeError<E> where E: std::error::Error {}
402
403impl<T> FromLdapType for Vec<T>
404where
405 T: FromStringLdapType,
406{
407 type Error = VecOfFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
408
409 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
410 where
411 Self: Sized,
412 {
413 if !values.binary_values.is_empty() {
414 return Err(
415 VecOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
416 entry_dn: values.entry_dn,
417 attribute_name: values.attribute_name,
418 },
419 );
420 }
421 values
422 .string_values
423 .into_iter()
424 .map(|v| <T as FromStringLdapType>::parse(&values.entry_dn, &values.attribute_name, v))
425 .collect::<Result<Self, <T as FromStringLdapType>::Error>>()
426 .map_err(VecOfFromStringLdapTypeError::PrimitiveValueConversionError)
427 }
428}
429
430#[derive(Debug, Clone)]
433pub enum OptionOfFromStringLdapTypeError<E> {
434 LdapShouldNotReturnBinaryResult {
437 entry_dn: String,
439 attribute_name: String,
441 },
442 LdapShouldNotReturnMultipleResults {
445 entry_dn: String,
447 attribute_name: String,
449 },
450 PrimitiveValueConversionError(E),
452}
453
454impl<E> std::fmt::Display for OptionOfFromStringLdapTypeError<E>
455where
456 E: std::error::Error,
457{
458 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459 match self {
460 Self::LdapShouldNotReturnBinaryResult {
461 entry_dn,
462 attribute_name,
463 } => {
464 write!(
465 f,
466 "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports String inputs"
467 )
468 }
469 Self::LdapShouldNotReturnMultipleResults {
470 entry_dn,
471 attribute_name,
472 } => {
473 write!(
474 f,
475 "encountered multiple string values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports String inputs"
476 )
477 }
478 Self::PrimitiveValueConversionError(err) => {
479 write!(
480 f,
481 "encountered error converting a primitive value from String: {err}",
482 )
483 }
484 }
485 }
486}
487
488impl<E> std::error::Error for OptionOfFromStringLdapTypeError<E> where E: std::error::Error {}
489
490impl<T> FromLdapType for Option<T>
491where
492 T: FromStringLdapType,
493{
494 type Error = OptionOfFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
495
496 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
497 where
498 Self: Sized,
499 {
500 if !values.binary_values.is_empty() {
501 return Err(
502 OptionOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
503 entry_dn: values.entry_dn,
504 attribute_name: values.attribute_name,
505 },
506 );
507 }
508 if values.string_values.len() > 1 {
509 return Err(
510 OptionOfFromStringLdapTypeError::LdapShouldNotReturnMultipleResults {
511 entry_dn: values.entry_dn,
512 attribute_name: values.attribute_name,
513 },
514 );
515 }
516 if let Some(value) = values.string_values.first() {
517 Ok(Some(
518 <T as FromStringLdapType>::parse(
519 &values.entry_dn,
520 &values.attribute_name,
521 value.to_owned(),
522 )
523 .map_err(OptionOfFromStringLdapTypeError::PrimitiveValueConversionError)?,
524 ))
525 } else {
526 Ok(None)
527 }
528 }
529}
530
531#[derive(Debug, Clone)]
534pub enum RequiredFromStringLdapTypeError<E> {
535 LdapShouldNotReturnBinaryResult {
538 entry_dn: String,
540 attribute_name: String,
542 },
543 LdapShouldReturnExactlyOneResult {
546 entry_dn: String,
548 attribute_name: String,
550 count: usize,
552 },
553 PrimitiveValueConversionError(E),
555}
556
557impl<E> std::fmt::Display for RequiredFromStringLdapTypeError<E>
558where
559 E: std::error::Error,
560{
561 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
562 match self {
563 Self::LdapShouldNotReturnBinaryResult {
564 entry_dn,
565 attribute_name,
566 } => {
567 write!(
568 f,
569 "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports String inputs"
570 )
571 }
572 Self::LdapShouldReturnExactlyOneResult {
573 entry_dn,
574 attribute_name,
575 count,
576 } => {
577 write!(
578 f,
579 "encountered {count} string values (expected exactly one) in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports String inputs"
580 )
581 }
582 Self::PrimitiveValueConversionError(err) => {
583 write!(
584 f,
585 "encountered error converting a primitive value from String: {err}",
586 )
587 }
588 }
589 }
590}
591
592impl<E> std::error::Error for RequiredFromStringLdapTypeError<E> where E: std::error::Error {}
593
594impl<T> FromLdapType for T
595where
596 T: FromStringLdapType,
597{
598 type Error = RequiredFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
599
600 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
601 where
602 Self: Sized,
603 {
604 if !values.binary_values.is_empty() {
605 return Err(
606 RequiredFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
607 entry_dn: values.entry_dn,
608 attribute_name: values.attribute_name,
609 },
610 );
611 }
612 if values.string_values.len() != 1 {
613 return Err(
614 RequiredFromStringLdapTypeError::LdapShouldReturnExactlyOneResult {
615 entry_dn: values.entry_dn,
616 attribute_name: values.attribute_name,
617 count: values.string_values.len(),
618 },
619 );
620 }
621 if let Some(value) = values.string_values.first() {
622 Ok(<T as FromStringLdapType>::parse(
623 &values.entry_dn,
624 &values.attribute_name,
625 value.to_owned(),
626 )
627 .map_err(RequiredFromStringLdapTypeError::PrimitiveValueConversionError)?)
628 } else {
629 Err(
630 RequiredFromStringLdapTypeError::LdapShouldReturnExactlyOneResult {
631 entry_dn: values.entry_dn,
632 attribute_name: values.attribute_name,
633 count: values.string_values.len(),
634 },
635 )
636 }
637 }
638}
639
640pub trait FromBinaryLdapType {
643 type Error;
645
646 fn parse(entry_dn: &str, attribute_name: &str, value: Vec<u8>) -> Result<Self, Self::Error>
652 where
653 Self: Sized;
654}
655
656#[derive(Debug, Clone, PartialEq, Eq)]
659pub struct UnexpectedBinaryValue {
660 source_entry_dn: String,
662 source_attribute_name: String,
664 conversion_target_name: String,
666 unexpected_value: Vec<u8>,
668}
669
670impl std::fmt::Display for UnexpectedBinaryValue {
671 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
672 write!(
673 f,
674 "Unexpected value in conversion of {} attribute {} to {}: {:?}",
675 self.source_entry_dn,
676 self.source_attribute_name,
677 self.conversion_target_name,
678 self.unexpected_value,
679 )
680 }
681}
682
683impl std::error::Error for UnexpectedBinaryValue {}
684
685impl FromBinaryLdapType for Vec<u8> {
686 type Error = std::convert::Infallible;
687
688 fn parse(_entry_dn: &str, _attribute_name: &str, value: Vec<u8>) -> Result<Self, Self::Error>
689 where
690 Self: Sized,
691 {
692 Ok(value)
693 }
694}
695
696#[derive(Debug, Clone)]
700pub struct Binary<T>(pub T);
701
702#[derive(Debug, Clone)]
705pub enum VecOfFromBinaryLdapTypeError<E> {
706 LdapShouldNotReturnStringResult {
709 entry_dn: String,
711 attribute_name: String,
713 },
714 PrimitiveValueConversionError(E),
716}
717
718impl<E> std::fmt::Display for VecOfFromBinaryLdapTypeError<E>
719where
720 E: std::error::Error,
721{
722 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
723 match self {
724 Self::LdapShouldNotReturnStringResult {
725 entry_dn,
726 attribute_name,
727 } => {
728 write!(
729 f,
730 "encountered String values in input for {entry_dn} attribute {attribute_name} when converting a Vec of a type that only supports binary inputs"
731 )
732 }
733 Self::PrimitiveValueConversionError(err) => {
734 write!(
735 f,
736 "encountered error converting a primitive value from binary: {err}",
737 )
738 }
739 }
740 }
741}
742
743impl<E> std::error::Error for VecOfFromBinaryLdapTypeError<E> where E: std::error::Error {}
744
745impl<T> FromLdapType for Binary<Vec<T>>
746where
747 T: FromBinaryLdapType,
748{
749 type Error = VecOfFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
750
751 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
752 where
753 Self: Sized,
754 {
755 if !values.string_values.is_empty() {
756 return Err(
757 VecOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
758 entry_dn: values.entry_dn,
759 attribute_name: values.attribute_name,
760 },
761 );
762 }
763 values
764 .binary_values
765 .into_iter()
766 .map(|v| <T as FromBinaryLdapType>::parse(&values.entry_dn, &values.attribute_name, v))
767 .collect::<Result<Vec<T>, <T as FromBinaryLdapType>::Error>>()
768 .map(Binary)
769 .map_err(VecOfFromBinaryLdapTypeError::PrimitiveValueConversionError)
770 }
771}
772
773#[derive(Debug, Clone)]
776pub enum OptionOfFromBinaryLdapTypeError<E> {
777 LdapShouldNotReturnStringResult {
780 entry_dn: String,
782 attribute_name: String,
784 },
785 LdapShouldNotReturnMultipleResults {
788 entry_dn: String,
790 attribute_name: String,
792 },
793 PrimitiveValueConversionError(E),
795}
796
797impl<E> std::fmt::Display for OptionOfFromBinaryLdapTypeError<E>
798where
799 E: std::error::Error,
800{
801 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
802 match self {
803 Self::LdapShouldNotReturnStringResult {
804 entry_dn,
805 attribute_name,
806 } => {
807 write!(
808 f,
809 "encountered String values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports binary inputs"
810 )
811 }
812 Self::LdapShouldNotReturnMultipleResults {
813 entry_dn,
814 attribute_name,
815 } => {
816 write!(
817 f,
818 "encountered multiple binary values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports binary inputs"
819 )
820 }
821 Self::PrimitiveValueConversionError(err) => {
822 write!(
823 f,
824 "encountered error converting a primitive value from binary: {err}",
825 )
826 }
827 }
828 }
829}
830
831impl<E> std::error::Error for OptionOfFromBinaryLdapTypeError<E> where E: std::error::Error {}
832
833impl<T> FromLdapType for Binary<Option<T>>
834where
835 T: FromBinaryLdapType,
836{
837 type Error = OptionOfFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
838
839 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
840 where
841 Self: Sized,
842 {
843 if !values.string_values.is_empty() {
844 return Err(
845 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
846 entry_dn: values.entry_dn,
847 attribute_name: values.attribute_name,
848 },
849 );
850 }
851 if values.binary_values.len() > 1 {
852 return Err(
853 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnMultipleResults {
854 entry_dn: values.entry_dn,
855 attribute_name: values.attribute_name,
856 },
857 );
858 }
859 if let Some(value) = values.binary_values.first() {
860 Ok(Self(Some(
861 <T as FromBinaryLdapType>::parse(
862 &values.entry_dn,
863 &values.attribute_name,
864 value.to_owned(),
865 )
866 .map_err(OptionOfFromBinaryLdapTypeError::PrimitiveValueConversionError)?,
867 )))
868 } else {
869 Ok(Self(None))
870 }
871 }
872}
873
874#[derive(Debug, Clone)]
877pub enum RequiredFromBinaryLdapTypeError<E> {
878 LdapShouldNotReturnStringResult {
881 entry_dn: String,
883 attribute_name: String,
885 },
886 LdapShouldReturnExactlyOneResult {
889 entry_dn: String,
891 attribute_name: String,
893 count: usize,
895 },
896 PrimitiveValueConversionError(E),
898}
899
900impl<E> std::fmt::Display for RequiredFromBinaryLdapTypeError<E>
901where
902 E: std::error::Error,
903{
904 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
905 match self {
906 Self::LdapShouldNotReturnStringResult {
907 entry_dn,
908 attribute_name,
909 } => {
910 write!(
911 f,
912 "encountered String values in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports binary inputs"
913 )
914 }
915 Self::LdapShouldReturnExactlyOneResult {
916 entry_dn,
917 attribute_name,
918 count,
919 } => {
920 write!(
921 f,
922 "encountered {count} binary values (expected exactly one) in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports binary inputs"
923 )
924 }
925 Self::PrimitiveValueConversionError(err) => {
926 write!(
927 f,
928 "encountered error converting a primitive value from binary: {err}",
929 )
930 }
931 }
932 }
933}
934
935impl<E> std::error::Error for RequiredFromBinaryLdapTypeError<E> where E: std::error::Error {}
936
937impl<T> FromLdapType for Binary<T>
938where
939 T: FromBinaryLdapType,
940{
941 type Error = RequiredFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
942
943 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
944 where
945 Self: Sized,
946 {
947 if !values.string_values.is_empty() {
948 return Err(
949 RequiredFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
950 entry_dn: values.entry_dn,
951 attribute_name: values.attribute_name,
952 },
953 );
954 }
955 if values.binary_values.len() != 1 {
956 return Err(
957 RequiredFromBinaryLdapTypeError::LdapShouldReturnExactlyOneResult {
958 entry_dn: values.entry_dn,
959 attribute_name: values.attribute_name,
960 count: values.string_values.len(),
961 },
962 );
963 }
964 if let Some(value) = values.binary_values.first() {
965 Ok(<T as FromBinaryLdapType>::parse(
966 &values.entry_dn,
967 &values.attribute_name,
968 value.to_owned(),
969 )
970 .map(Binary)
971 .map_err(RequiredFromBinaryLdapTypeError::PrimitiveValueConversionError)?)
972 } else {
973 Err(
974 RequiredFromBinaryLdapTypeError::LdapShouldReturnExactlyOneResult {
975 entry_dn: values.entry_dn,
976 attribute_name: values.attribute_name,
977 count: values.string_values.len(),
978 },
979 )
980 }
981 }
982}