1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
use crate::libyml::safe_cstr;
use memchr::memchr;
use std::{
fmt::{self, Debug, Display},
ops::Deref,
};
/// Custom error type for Tag operations.
#[derive(Clone, Copy, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct TagFormatError;
impl Display for TagFormatError {
/// Formats the error message for display.
///
/// # Arguments
///
/// * `f` - The formatter to write the error message to.
///
/// # Returns
///
/// Returns `fmt::Result` indicating the success or failure of the operation.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Error occurred while formatting tag")
}
}
impl std::error::Error for TagFormatError {}
/// Represents a tag in a YAML document.
/// A tag specifies the data type or semantic meaning of a value.
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
pub struct Tag(pub(in crate::libyml) Box<[u8]>);
impl Tag {
/// The null tag, representing a null value.
pub const NULL: &'static str = "tag:yaml.org,2002:null";
/// The bool tag, representing a boolean value.
pub const BOOL: &'static str = "tag:yaml.org,2002:bool";
/// The int tag, representing an integer value.
pub const INT: &'static str = "tag:yaml.org,2002:int";
/// The float tag, representing a floating-point value.
pub const FLOAT: &'static str = "tag:yaml.org,2002:float";
/// Checks if the tag starts with the given prefix.
///
/// # Arguments
///
/// * `prefix` - The prefix to check against.
///
/// # Returns
///
/// Returns `Ok(true)` if the tag starts with the given prefix, `Ok(false)` otherwise.
/// Returns an error if the prefix is longer than the tag.
///
/// # Errors
///
/// Returns `TagFormatError` if the prefix length is greater than the tag length.
pub fn starts_with(
&self,
prefix: &str,
) -> Result<bool, TagFormatError> {
if prefix.len() > self.0.len() {
Err(TagFormatError)
} else {
let prefix_bytes = prefix.as_bytes();
let tag_bytes = &self.0[..prefix_bytes.len()];
Ok(tag_bytes == prefix_bytes)
}
}
/// Creates a new `Tag` instance from a `&str` input.
///
/// # Arguments
///
/// * `tag_str` - The string representing the tag.
///
/// # Returns
///
/// Returns a `Tag` instance representing the specified tag string.
pub fn new(tag_str: &str) -> Tag {
Tag(Box::from(tag_str.as_bytes()))
}
}
impl PartialEq<str> for Tag {
/// Checks if the tag is equal to the given string.
///
/// # Arguments
///
/// * `other` - The string to compare against.
///
/// # Returns
///
/// Returns `true` if the tag is equal to the given string, `false` otherwise.
fn eq(&self, other: &str) -> bool {
self.0 == other.as_bytes().into()
}
}
impl PartialEq<&str> for Tag {
/// Checks if the tag is equal to the given string slice.
///
/// # Arguments
///
/// * `other` - The string slice to compare against.
///
/// # Returns
///
/// Returns `true` if the tag is equal to the given string slice, `false` otherwise.
fn eq(&self, other: &&str) -> bool {
self.0 == other.as_bytes().into()
}
}
impl Deref for Tag {
type Target = [u8];
/// Dereferences the tag to its underlying byte slice.
///
/// # Returns
///
/// Returns a reference to the underlying byte slice of the tag.
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Debug for Tag {
/// Formats the tag for debugging purposes.
///
/// # Arguments
///
/// * `formatter` - The formatter to write the debug output to.
///
/// # Returns
///
/// Returns `Ok(())` if the formatting was successful, or an error otherwise.
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(null_pos) = memchr(b'\0', &self.0) {
safe_cstr::debug_lossy(&self.0[..null_pos], formatter)
} else {
safe_cstr::debug_lossy(&self.0, formatter)
}
}
}