tiberius/tds/
xml.rs

1//! The XML containers
2use super::codec::Encode;
3use bytes::{BufMut, BytesMut};
4use std::borrow::BorrowMut;
5use std::sync::Arc;
6
7/// Provides information of the location for the schema.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct XmlSchema {
10    db_name: String,
11    owner: String,
12    collection: String,
13}
14
15impl XmlSchema {
16    pub(crate) fn new(
17        db_name: impl ToString,
18        owner: impl ToString,
19        collection: impl ToString,
20    ) -> Self {
21        Self {
22            db_name: db_name.to_string(),
23            owner: owner.to_string(),
24            collection: collection.to_string(),
25        }
26    }
27
28    /// Specifies the name of the database where the schema collection is defined.
29    pub fn db_name(&self) -> &str {
30        &self.db_name
31    }
32
33    /// Specifies the name of the relational schema containing the schema collection.
34    pub fn owner(&self) -> &str {
35        &self.owner
36    }
37
38    /// Specifies the name of the XML schema collection to which the type is
39    /// bound.
40    pub fn collection(&self) -> &str {
41        &self.collection
42    }
43}
44
45/// A representation of XML data in TDS. Holds the data as a UTF-8 string and
46/// and optional information about the schema.
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct XmlData {
49    data: String,
50    schema: Option<Arc<XmlSchema>>,
51}
52
53impl XmlData {
54    /// Create a new XmlData with the given string. Validation of the XML data
55    /// happens in the database.
56    pub fn new(data: impl ToString) -> Self {
57        Self {
58            data: data.to_string(),
59            schema: None,
60        }
61    }
62
63    pub(crate) fn set_schema(&mut self, schema: Arc<XmlSchema>) {
64        self.schema = Some(schema);
65    }
66
67    /// Returns information about the schema of the XML file, if existing.
68    #[allow(clippy::option_as_ref_deref)]
69    pub fn schema(&self) -> Option<&XmlSchema> {
70        self.schema.as_ref().map(|s| &**s)
71    }
72
73    /// Takes the XML string out from the struct.
74    pub fn into_string(self) -> String {
75        self.data
76    }
77}
78
79impl std::fmt::Display for XmlData {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "{}", self.data)
82    }
83}
84
85impl AsRef<str> for XmlData {
86    fn as_ref(&self) -> &str {
87        self.data.as_ref()
88    }
89}
90
91impl Encode<BytesMut> for XmlData {
92    fn encode(self, dst: &mut BytesMut) -> crate::Result<()> {
93        // unknown size
94        dst.put_u64_le(0xfffffffffffffffe_u64);
95
96        // first blob
97        let mut length = 0u32;
98        let len_pos = dst.len();
99
100        // writing the length later
101        dst.put_u32_le(length);
102
103        for chr in self.data.encode_utf16() {
104            length += 1;
105            dst.put_u16_le(chr);
106        }
107
108        // PLP_TERMINATOR, no next blobs
109        dst.put_u32_le(0);
110
111        let dst: &mut [u8] = dst.borrow_mut();
112        let mut dst = &mut dst[len_pos..];
113        dst.put_u32_le(length * 2);
114
115        Ok(())
116    }
117}