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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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(|_| 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 VecOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
383 entry_dn,
384 attribute_name,
385 } => {
386 write!(f, "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting a Vec of a type that only supports String inputs")
387 }
388 VecOfFromStringLdapTypeError::PrimitiveValueConversionError(err) => {
389 write!(
390 f,
391 "encountered error converting a primitive value from String: {}",
392 err
393 )
394 }
395 }
396 }
397}
398
399impl<E> std::error::Error for VecOfFromStringLdapTypeError<E> where E: std::error::Error {}
400
401impl<T> FromLdapType for Vec<T>
402where
403 T: FromStringLdapType,
404{
405 type Error = VecOfFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
406
407 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
408 where
409 Self: Sized,
410 {
411 if !values.binary_values.is_empty() {
412 return Err(
413 VecOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
414 entry_dn: values.entry_dn,
415 attribute_name: values.attribute_name,
416 },
417 );
418 }
419 values
420 .string_values
421 .into_iter()
422 .map(|v| <T as FromStringLdapType>::parse(&values.entry_dn, &values.attribute_name, v))
423 .collect::<Result<Vec<T>, <T as FromStringLdapType>::Error>>()
424 .map_err(VecOfFromStringLdapTypeError::PrimitiveValueConversionError)
425 }
426}
427
428#[derive(Debug, Clone)]
431pub enum OptionOfFromStringLdapTypeError<E> {
432 LdapShouldNotReturnBinaryResult {
435 entry_dn: String,
437 attribute_name: String,
439 },
440 LdapShouldNotReturnMultipleResults {
443 entry_dn: String,
445 attribute_name: String,
447 },
448 PrimitiveValueConversionError(E),
450}
451
452impl<E> std::fmt::Display for OptionOfFromStringLdapTypeError<E>
453where
454 E: std::error::Error,
455{
456 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
457 match self {
458 OptionOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
459 entry_dn,
460 attribute_name,
461 } => {
462 write!(f, "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports String inputs")
463 }
464 OptionOfFromStringLdapTypeError::LdapShouldNotReturnMultipleResults {
465 entry_dn,
466 attribute_name,
467 } => {
468 write!(f, "encountered multiple string values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports String inputs")
469 }
470 OptionOfFromStringLdapTypeError::PrimitiveValueConversionError(err) => {
471 write!(
472 f,
473 "encountered error converting a primitive value from String: {}",
474 err
475 )
476 }
477 }
478 }
479}
480
481impl<E> std::error::Error for OptionOfFromStringLdapTypeError<E> where E: std::error::Error {}
482
483impl<T> FromLdapType for Option<T>
484where
485 T: FromStringLdapType,
486{
487 type Error = OptionOfFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
488
489 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
490 where
491 Self: Sized,
492 {
493 if !values.binary_values.is_empty() {
494 return Err(
495 OptionOfFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
496 entry_dn: values.entry_dn,
497 attribute_name: values.attribute_name,
498 },
499 );
500 }
501 if values.string_values.len() > 1 {
502 return Err(
503 OptionOfFromStringLdapTypeError::LdapShouldNotReturnMultipleResults {
504 entry_dn: values.entry_dn,
505 attribute_name: values.attribute_name,
506 },
507 );
508 }
509 if let Some(value) = values.string_values.first() {
510 Ok(Some(
511 <T as FromStringLdapType>::parse(
512 &values.entry_dn,
513 &values.attribute_name,
514 value.to_owned(),
515 )
516 .map_err(OptionOfFromStringLdapTypeError::PrimitiveValueConversionError)?,
517 ))
518 } else {
519 Ok(None)
520 }
521 }
522}
523
524#[derive(Debug, Clone)]
527pub enum RequiredFromStringLdapTypeError<E> {
528 LdapShouldNotReturnBinaryResult {
531 entry_dn: String,
533 attribute_name: String,
535 },
536 LdapShouldReturnExactlyOneResult {
539 entry_dn: String,
541 attribute_name: String,
543 count: usize,
545 },
546 PrimitiveValueConversionError(E),
548}
549
550impl<E> std::fmt::Display for RequiredFromStringLdapTypeError<E>
551where
552 E: std::error::Error,
553{
554 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
555 match self {
556 RequiredFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
557 entry_dn,
558 attribute_name,
559 } => {
560 write!(f, "encountered binary values in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports String inputs")
561 }
562 RequiredFromStringLdapTypeError::LdapShouldReturnExactlyOneResult {
563 entry_dn,
564 attribute_name,
565 count,
566 } => {
567 write!(f, "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")
568 }
569 RequiredFromStringLdapTypeError::PrimitiveValueConversionError(err) => {
570 write!(
571 f,
572 "encountered error converting a primitive value from String: {}",
573 err
574 )
575 }
576 }
577 }
578}
579
580impl<E> std::error::Error for RequiredFromStringLdapTypeError<E> where E: std::error::Error {}
581
582impl<T> FromLdapType for T
583where
584 T: FromStringLdapType,
585{
586 type Error = RequiredFromStringLdapTypeError<<T as FromStringLdapType>::Error>;
587
588 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
589 where
590 Self: Sized,
591 {
592 if !values.binary_values.is_empty() {
593 return Err(
594 RequiredFromStringLdapTypeError::LdapShouldNotReturnBinaryResult {
595 entry_dn: values.entry_dn,
596 attribute_name: values.attribute_name,
597 },
598 );
599 }
600 if values.string_values.len() != 1 {
601 return Err(
602 RequiredFromStringLdapTypeError::LdapShouldReturnExactlyOneResult {
603 entry_dn: values.entry_dn,
604 attribute_name: values.attribute_name,
605 count: values.string_values.len(),
606 },
607 );
608 }
609 if let Some(value) = values.string_values.first() {
610 Ok(<T as FromStringLdapType>::parse(
611 &values.entry_dn,
612 &values.attribute_name,
613 value.to_owned(),
614 )
615 .map_err(RequiredFromStringLdapTypeError::PrimitiveValueConversionError)?)
616 } else {
617 Err(
618 RequiredFromStringLdapTypeError::LdapShouldReturnExactlyOneResult {
619 entry_dn: values.entry_dn,
620 attribute_name: values.attribute_name,
621 count: values.string_values.len(),
622 },
623 )
624 }
625 }
626}
627
628pub trait FromBinaryLdapType {
631 type Error;
633
634 fn parse(entry_dn: &str, attribute_name: &str, value: Vec<u8>) -> Result<Self, Self::Error>
640 where
641 Self: Sized;
642}
643
644#[derive(Debug, Clone, PartialEq, Eq)]
647pub struct UnexpectedBinaryValue {
648 source_entry_dn: String,
650 source_attribute_name: String,
652 conversion_target_name: String,
654 unexpected_value: Vec<u8>,
656}
657
658impl std::fmt::Display for UnexpectedBinaryValue {
659 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
660 write!(
661 f,
662 "Unexpected value in conversion of {} attribute {} to {}: {:?}",
663 self.source_entry_dn,
664 self.source_attribute_name,
665 self.conversion_target_name,
666 self.unexpected_value,
667 )
668 }
669}
670
671impl std::error::Error for UnexpectedBinaryValue {}
672
673impl FromBinaryLdapType for Vec<u8> {
674 type Error = std::convert::Infallible;
675
676 fn parse(_entry_dn: &str, _attribute_name: &str, value: Vec<u8>) -> Result<Self, Self::Error>
677 where
678 Self: Sized,
679 {
680 Ok(value)
681 }
682}
683
684#[derive(Debug, Clone)]
688pub struct Binary<T>(pub T);
689
690#[derive(Debug, Clone)]
693pub enum VecOfFromBinaryLdapTypeError<E> {
694 LdapShouldNotReturnStringResult {
697 entry_dn: String,
699 attribute_name: String,
701 },
702 PrimitiveValueConversionError(E),
704}
705
706impl<E> std::fmt::Display for VecOfFromBinaryLdapTypeError<E>
707where
708 E: std::error::Error,
709{
710 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
711 match self {
712 VecOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
713 entry_dn,
714 attribute_name,
715 } => {
716 write!(f, "encountered String values in input for {entry_dn} attribute {attribute_name} when converting a Vec of a type that only supports binary inputs")
717 }
718 VecOfFromBinaryLdapTypeError::PrimitiveValueConversionError(err) => {
719 write!(
720 f,
721 "encountered error converting a primitive value from binary: {}",
722 err
723 )
724 }
725 }
726 }
727}
728
729impl<E> std::error::Error for VecOfFromBinaryLdapTypeError<E> where E: std::error::Error {}
730
731impl<T> FromLdapType for Binary<Vec<T>>
732where
733 T: FromBinaryLdapType,
734{
735 type Error = VecOfFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
736
737 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
738 where
739 Self: Sized,
740 {
741 if !values.string_values.is_empty() {
742 return Err(
743 VecOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
744 entry_dn: values.entry_dn,
745 attribute_name: values.attribute_name,
746 },
747 );
748 }
749 values
750 .binary_values
751 .into_iter()
752 .map(|v| <T as FromBinaryLdapType>::parse(&values.entry_dn, &values.attribute_name, v))
753 .collect::<Result<Vec<T>, <T as FromBinaryLdapType>::Error>>()
754 .map(Binary)
755 .map_err(VecOfFromBinaryLdapTypeError::PrimitiveValueConversionError)
756 }
757}
758
759#[derive(Debug, Clone)]
762pub enum OptionOfFromBinaryLdapTypeError<E> {
763 LdapShouldNotReturnStringResult {
766 entry_dn: String,
768 attribute_name: String,
770 },
771 LdapShouldNotReturnMultipleResults {
774 entry_dn: String,
776 attribute_name: String,
778 },
779 PrimitiveValueConversionError(E),
781}
782
783impl<E> std::fmt::Display for OptionOfFromBinaryLdapTypeError<E>
784where
785 E: std::error::Error,
786{
787 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
788 match self {
789 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
790 entry_dn,
791 attribute_name,
792 } => {
793 write!(f, "encountered String values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports binary inputs")
794 }
795 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnMultipleResults {
796 entry_dn,
797 attribute_name,
798 } => {
799 write!(f, "encountered multiple binary values in input for {entry_dn} attribute {attribute_name} when converting an Option of a type that only supports binary inputs")
800 }
801 OptionOfFromBinaryLdapTypeError::PrimitiveValueConversionError(err) => {
802 write!(
803 f,
804 "encountered error converting a primitive value from binary: {}",
805 err
806 )
807 }
808 }
809 }
810}
811
812impl<E> std::error::Error for OptionOfFromBinaryLdapTypeError<E> where E: std::error::Error {}
813
814impl<T> FromLdapType for Binary<Option<T>>
815where
816 T: FromBinaryLdapType,
817{
818 type Error = OptionOfFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
819
820 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
821 where
822 Self: Sized,
823 {
824 if !values.string_values.is_empty() {
825 return Err(
826 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
827 entry_dn: values.entry_dn,
828 attribute_name: values.attribute_name,
829 },
830 );
831 }
832 if values.binary_values.len() > 1 {
833 return Err(
834 OptionOfFromBinaryLdapTypeError::LdapShouldNotReturnMultipleResults {
835 entry_dn: values.entry_dn,
836 attribute_name: values.attribute_name,
837 },
838 );
839 }
840 if let Some(value) = values.binary_values.first() {
841 Ok(Binary(Some(
842 <T as FromBinaryLdapType>::parse(
843 &values.entry_dn,
844 &values.attribute_name,
845 value.to_owned(),
846 )
847 .map_err(OptionOfFromBinaryLdapTypeError::PrimitiveValueConversionError)?,
848 )))
849 } else {
850 Ok(Binary(None))
851 }
852 }
853}
854
855#[derive(Debug, Clone)]
858pub enum RequiredFromBinaryLdapTypeError<E> {
859 LdapShouldNotReturnStringResult {
862 entry_dn: String,
864 attribute_name: String,
866 },
867 LdapShouldReturnExactlyOneResult {
870 entry_dn: String,
872 attribute_name: String,
874 count: usize,
876 },
877 PrimitiveValueConversionError(E),
879}
880
881impl<E> std::fmt::Display for RequiredFromBinaryLdapTypeError<E>
882where
883 E: std::error::Error,
884{
885 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
886 match self {
887 RequiredFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
888 entry_dn,
889 attribute_name,
890 } => {
891 write!(f, "encountered String values in input for {entry_dn} attribute {attribute_name} when converting a required value of a type that only supports binary inputs")
892 }
893 RequiredFromBinaryLdapTypeError::LdapShouldReturnExactlyOneResult {
894 entry_dn,
895 attribute_name,
896 count,
897 } => {
898 write!(f, "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")
899 }
900 RequiredFromBinaryLdapTypeError::PrimitiveValueConversionError(err) => {
901 write!(
902 f,
903 "encountered error converting a primitive value from binary: {}",
904 err
905 )
906 }
907 }
908 }
909}
910
911impl<E> std::error::Error for RequiredFromBinaryLdapTypeError<E> where E: std::error::Error {}
912
913impl<T> FromLdapType for Binary<T>
914where
915 T: FromBinaryLdapType,
916{
917 type Error = RequiredFromBinaryLdapTypeError<<T as FromBinaryLdapType>::Error>;
918
919 fn parse(values: LdapAttributeResultValues) -> Result<Self, Self::Error>
920 where
921 Self: Sized,
922 {
923 if !values.string_values.is_empty() {
924 return Err(
925 RequiredFromBinaryLdapTypeError::LdapShouldNotReturnStringResult {
926 entry_dn: values.entry_dn,
927 attribute_name: values.attribute_name,
928 },
929 );
930 }
931 if values.binary_values.len() != 1 {
932 return Err(
933 RequiredFromBinaryLdapTypeError::LdapShouldReturnExactlyOneResult {
934 entry_dn: values.entry_dn,
935 attribute_name: values.attribute_name,
936 count: values.string_values.len(),
937 },
938 );
939 }
940 if let Some(value) = values.binary_values.first() {
941 Ok(<T as FromBinaryLdapType>::parse(
942 &values.entry_dn,
943 &values.attribute_name,
944 value.to_owned(),
945 )
946 .map(Binary)
947 .map_err(RequiredFromBinaryLdapTypeError::PrimitiveValueConversionError)?)
948 } else {
949 Err(
950 RequiredFromBinaryLdapTypeError::LdapShouldReturnExactlyOneResult {
951 entry_dn: values.entry_dn,
952 attribute_name: values.attribute_name,
953 count: values.string_values.len(),
954 },
955 )
956 }
957 }
958}