xml_sec/xmldsig/
extension.rs1use crate::document::{DocumentView, NodeIdentity, XmlDocumentError};
7use structured_asn1::memory::{MemoryError, Work};
8
9mod scalar;
10pub use scalar::*;
11mod tree;
12pub use tree::*;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum BooleanAttribute {
17 Absent,
19 Value(bool),
21 Malformed,
23}
24
25#[derive(Debug, thiserror::Error)]
27pub enum ScalarError {
28 #[error(transparent)]
30 Document(#[from] XmlDocumentError),
31 #[error("XML scalar owner is not an element")]
33 NotElement,
34 #[error("XML scalar resource failure: {0}")]
36 Resource(MemoryError),
37}
38
39pub(super) fn charge_bytes<W: Work>(work: &W, bytes: usize) -> Result<(), ScalarError> {
40 let bytes =
41 u64::try_from(bytes).map_err(|_| ScalarError::Resource(MemoryError::WorkExceeded))?;
42 work.charge_work(bytes).map_err(ScalarError::Resource)
43}
44
45pub fn boolean_attribute<W: Work>(
52 view: DocumentView<'_>,
53 owner: NodeIdentity,
54 namespace: Option<&str>,
55 local_name: &str,
56 work: &W,
57) -> Result<BooleanAttribute, ScalarError> {
58 work.charge_work(1).map_err(ScalarError::Resource)?;
59 let node = view.resolve_node(owner)?;
60 if !node.is_element() {
61 return Err(ScalarError::NotElement);
62 }
63 for attribute in node.attributes() {
64 work.charge_work(1).map_err(ScalarError::Resource)?;
65 charge_bytes(work, attribute.name().len())?;
66 if attribute.name() != local_name {
67 continue;
68 }
69 if let Some(uri) = attribute.namespace() {
70 charge_bytes(work, uri.len())?;
71 }
72 if attribute.namespace() != namespace {
73 continue;
74 }
75 let value = attribute.value();
76 charge_bytes(work, value.len())?;
77 work.charge_work(5).map_err(ScalarError::Resource)?;
78 return Ok(match value.trim_matches([' ', '\t', '\r', '\n']) {
84 "true" | "1" => BooleanAttribute::Value(true),
85 "false" | "0" => BooleanAttribute::Value(false),
86 _ => BooleanAttribute::Malformed,
87 });
88 }
89 Ok(BooleanAttribute::Absent)
90}