1 //! [![github]](https://github.com/dtolnay/semver) [![crates-io]](https://crates.io/crates/semver) [![docs-rs]](https://docs.rs/semver) 2 //! 3 //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github 4 //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust 5 //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K 6 //! 7 //! <br> 8 //! 9 //! A parser and evaluator for Cargo's flavor of Semantic Versioning. 10 //! 11 //! Semantic Versioning (see <https://semver.org>) is a guideline for how 12 //! version numbers are assigned and incremented. It is widely followed within 13 //! the Cargo/crates.io ecosystem for Rust. 14 //! 15 //! <br> 16 //! 17 //! # Example 18 //! 19 //! ``` 20 //! use semver::{BuildMetadata, Prerelease, Version, VersionReq}; 21 //! 22 //! fn main() { 23 //! let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap(); 24 //! 25 //! // Check whether this requirement matches version 1.2.3-alpha.1 (no) 26 //! let version = Version { 27 //! major: 1, 28 //! minor: 2, 29 //! patch: 3, 30 //! pre: Prerelease::new("alpha.1").unwrap(), 31 //! build: BuildMetadata::EMPTY, 32 //! }; 33 //! assert!(!req.matches(&version)); 34 //! 35 //! // Check whether it matches 1.3.0 (yes it does) 36 //! let version = Version::parse("1.3.0").unwrap(); 37 //! assert!(req.matches(&version)); 38 //! } 39 //! ``` 40 //! 41 //! <br><br> 42 //! 43 //! # Scope of this crate 44 //! 45 //! Besides Cargo, several other package ecosystems and package managers for 46 //! other languages also use SemVer: RubyGems/Bundler for Ruby, npm for 47 //! JavaScript, Composer for PHP, CocoaPods for Objective-C... 48 //! 49 //! The `semver` crate is specifically intended to implement Cargo's 50 //! interpretation of Semantic Versioning. 51 //! 52 //! Where the various tools differ in their interpretation or implementation of 53 //! the spec, this crate follows the implementation choices made by Cargo. If 54 //! you are operating on version numbers from some other package ecosystem, you 55 //! will want to use a different semver library which is appropriate to that 56 //! ecosystem. 57 //! 58 //! The extent of Cargo's SemVer support is documented in the *[Specifying 59 //! Dependencies]* chapter of the Cargo reference. 60 //! 61 //! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html 62 63 #![doc(html_root_url = "https://docs.rs/semver/1.0.4")] 64 #![cfg_attr(doc_cfg, feature(doc_cfg))] 65 #![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)] 66 #![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))] 67 #![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))] 68 #![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))] 69 #![allow( 70 clippy::cast_lossless, 71 clippy::cast_possible_truncation, 72 clippy::doc_markdown, 73 clippy::items_after_statements, 74 clippy::match_bool, 75 clippy::missing_errors_doc, 76 clippy::must_use_candidate, 77 clippy::needless_doctest_main, 78 clippy::option_if_let_else, 79 clippy::ptr_as_ptr, 80 clippy::redundant_else, 81 clippy::semicolon_if_nothing_returned, // https://github.com/rust-lang/rust-clippy/issues/7324 82 clippy::similar_names, 83 clippy::unnested_or_patterns, 84 clippy::unseparated_literal_suffix, 85 clippy::wildcard_imports 86 )] 87 88 #[cfg(not(no_alloc_crate))] 89 extern crate alloc; 90 91 mod backport; 92 mod display; 93 mod error; 94 mod eval; 95 mod identifier; 96 mod impls; 97 mod parse; 98 99 #[cfg(feature = "serde")] 100 mod serde; 101 102 use crate::alloc::vec::Vec; 103 use crate::identifier::Identifier; 104 use core::str::FromStr; 105 106 #[allow(unused_imports)] 107 use crate::backport::*; 108 109 pub use crate::parse::Error; 110 111 /// **SemVer version** as defined by <https://semver.org>. 112 /// 113 /// # Syntax 114 /// 115 /// - The major, minor, and patch numbers may be any integer 0 through u64::MAX. 116 /// When representing a SemVer version as a string, each number is written as 117 /// a base 10 integer. For example, `1.0.119`. 118 /// 119 /// - Leading zeros are forbidden in those positions. For example `1.01.00` is 120 /// invalid as a SemVer version. 121 /// 122 /// - The pre-release identifier, if present, must conform to the syntax 123 /// documented for [`Prerelease`]. 124 /// 125 /// - The build metadata, if present, must conform to the syntax documented for 126 /// [`BuildMetadata`]. 127 /// 128 /// - Whitespace is not allowed anywhere in the version. 129 /// 130 /// # Total ordering 131 /// 132 /// Given any two SemVer versions, one is less than, greater than, or equal to 133 /// the other. Versions may be compared against one another using Rust's usual 134 /// comparison operators. 135 /// 136 /// - The major, minor, and patch number are compared numerically from left to 137 /// right, lexicographically ordered as a 3-tuple of integers. So for example 138 /// version `1.5.0` is less than version `1.19.0`, despite the fact that 139 /// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5 140 /// as real numbers. 141 /// 142 /// - When major, minor, and patch are equal, a pre-release version is 143 /// considered less than the ordinary release: version `1.0.0-alpha.1` is 144 /// less than version `1.0.0`. 145 /// 146 /// - Two pre-releases of the same major, minor, patch are compared by 147 /// lexicographic ordering of dot-separated components of the pre-release 148 /// string. 149 /// 150 /// - Identifiers consisting of only digits are compared 151 /// numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`. 152 /// 153 /// - Identifiers that contain a letter or hyphen are compared in ASCII sort 154 /// order: `1.0.0-pre12` is less than `1.0.0-pre8`. 155 /// 156 /// - Any numeric identifier is always less than any non-numeric 157 /// identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`. 158 /// 159 /// Example: `1.0.0-alpha` < `1.0.0-alpha.1` < `1.0.0-alpha.beta` < `1.0.0-beta` < `1.0.0-beta.2` < `1.0.0-beta.11` < `1.0.0-rc.1` < `1.0.0` 160 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 161 pub struct Version { 162 pub major: u64, 163 pub minor: u64, 164 pub patch: u64, 165 pub pre: Prerelease, 166 pub build: BuildMetadata, 167 } 168 169 /// **SemVer version requirement** describing the intersection of some version 170 /// comparators, such as `>=1.2.3, <1.8`. 171 /// 172 /// # Syntax 173 /// 174 /// - Either `*` (meaning "any"), or one or more comma-separated comparators. 175 /// 176 /// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated 177 /// by optional whitespace. For example `>=1.0.0` or `>=1.0`. 178 /// 179 /// - Build metadata is syntactically permitted on the partial versions, but is 180 /// completely ignored, as it's never relevant to whether any comparator 181 /// matches a particular version. 182 /// 183 /// - Whitespace is permitted around commas and around operators. Whitespace is 184 /// not permitted within a partial version, i.e. anywhere between the major 185 /// version number and its minor, patch, pre-release, or build metadata. 186 #[derive(Default, Clone, Eq, PartialEq, Hash, Debug)] 187 pub struct VersionReq { 188 pub comparators: Vec<Comparator>, 189 } 190 191 /// A pair of comparison operator and partial version, such as `>=1.2`. Forms 192 /// one piece of a VersionReq. 193 #[derive(Clone, Eq, PartialEq, Hash, Debug)] 194 pub struct Comparator { 195 pub op: Op, 196 pub major: u64, 197 pub minor: Option<u64>, 198 /// Patch is only allowed if minor is Some. 199 pub patch: Option<u64>, 200 /// Non-empty pre-release is only allowed if patch is Some. 201 pub pre: Prerelease, 202 } 203 204 /// SemVer comparison operator: `=`, `>`, `>=`, `<`, `<=`, `~`, `^`, `*`. 205 /// 206 /// # Op::Exact 207 /// -  **`=I.J.K`** — exactly the version I.J.K 208 /// -  **`=I.J`** — equivalent to `>=I.J.0, <I.(J+1).0` 209 /// -  **`=I`** — equivalent to `>=I.0.0, <(I+1).0.0` 210 /// 211 /// # Op::Greater 212 /// -  **`>I.J.K`** 213 /// -  **`>I.J`** — equivalent to `>=I.(J+1).0` 214 /// -  **`>I`** — equivalent to `>=(I+1).0.0` 215 /// 216 /// # Op::GreaterEq 217 /// -  **`>=I.J.K`** 218 /// -  **`>=I.J`** — equivalent to `>=I.J.0` 219 /// -  **`>=I`** — equivalent to `>=I.0.0` 220 /// 221 /// # Op::Less 222 /// -  **`<I.J.K`** 223 /// -  **`<I.J`** — equivalent to `<I.J.0` 224 /// -  **`<I`** — equivalent to `<I.0.0` 225 /// 226 /// # Op::LessEq 227 /// -  **`<=I.J.K`** 228 /// -  **`<=I.J`** — equivalent to `<I.(J+1).0` 229 /// -  **`<=I`** — equivalent to `<(I+1).0.0` 230 /// 231 /// # Op::Tilde ("patch" updates) 232 /// *Tilde requirements allow the **patch** part of the semver version (the third number) to increase.* 233 /// -  **`~I.J.K`** — equivalent to `>=I.J.K, <I.(J+1).0` 234 /// -  **`~I.J`** — equivalent to `=I.J` 235 /// -  **`~I`** — equivalent to `=I` 236 /// 237 /// # Op::Caret ("compatible" updates) 238 /// *Caret requirements allow parts that are **right of the first nonzero** part of the semver version to increase.* 239 /// -  **`^I.J.K`** (for I\>0) — equivalent to `>=I.J.K, <(I+1).0.0` 240 /// -  **`^0.J.K`** (for J\>0) — equivalent to `>=0.J.K, <0.(J+1).0` 241 /// -  **`^0.0.K`** — equivalent to `=0.0.K` 242 /// -  **`^I.J`** (for I\>0 or J\>0) — equivalent to `^I.J.0` 243 /// -  **`^0.0`** — equivalent to `=0.0` 244 /// -  **`^I`** — equivalent to `=I` 245 /// 246 /// # Op::Wildcard 247 /// -  **`I.J.*`** — equivalent to `=I.J` 248 /// -  **`I.*`** or **`I.*.*`** — equivalent to `=I` 249 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] 250 #[cfg_attr(not(no_non_exhaustive), non_exhaustive)] 251 pub enum Op { 252 Exact, 253 Greater, 254 GreaterEq, 255 Less, 256 LessEq, 257 Tilde, 258 Caret, 259 Wildcard, 260 261 #[cfg(no_non_exhaustive)] // rustc <1.40 262 #[doc(hidden)] 263 __NonExhaustive, 264 } 265 266 /// Optional pre-release identifier on a version string. This comes after `-` in 267 /// a SemVer version, like `1.0.0-alpha.1` 268 /// 269 /// # Examples 270 /// 271 /// Some real world pre-release idioms drawn from crates.io: 272 /// 273 /// - **[mio]** <code>0.7.0-<b>alpha.1</b></code> — the most common style 274 /// for numbering pre-releases. 275 /// 276 /// - **[pest]** <code>1.0.0-<b>beta.8</b></code>, <code>1.0.0-<b>rc.0</b></code> 277 /// — this crate makes a distinction between betas and release 278 /// candidates. 279 /// 280 /// - **[sassers]** <code>0.11.0-<b>shitshow</b></code> — ???. 281 /// 282 /// - **[atomic-utils]** <code>0.0.0-<b>reserved</b></code> — a squatted 283 /// crate name. 284 /// 285 /// [mio]: https://crates.io/crates/mio 286 /// [pest]: https://crates.io/crates/pest 287 /// [atomic-utils]: https://crates.io/crates/atomic-utils 288 /// [sassers]: https://crates.io/crates/sassers 289 /// 290 /// *Tip:* Be aware that if you are planning to number your own pre-releases, 291 /// you should prefer to separate the numeric part from any non-numeric 292 /// identifiers by using a dot in between. That is, prefer pre-releases 293 /// `alpha.1`, `alpha.2`, etc rather than `alpha1`, `alpha2` etc. The SemVer 294 /// spec's rule for pre-release precedence has special treatment of numeric 295 /// components in the pre-release string, but only if there are no non-digit 296 /// characters in the same dot-separated component. So you'd have `alpha.2` < 297 /// `alpha.11` as intended, but `alpha11` < `alpha2`. 298 /// 299 /// # Syntax 300 /// 301 /// Pre-release strings are a series of dot separated identifiers immediately 302 /// following the patch version. Identifiers must comprise only ASCII 303 /// alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must not be 304 /// empty. Numeric identifiers must not include leading zeros. 305 /// 306 /// # Total ordering 307 /// 308 /// Pre-releases have a total order defined by the SemVer spec. It uses 309 /// lexicographic ordering of dot-separated components. Identifiers consisting 310 /// of only digits are compared numerically. Otherwise, identifiers are compared 311 /// in ASCII sort order. Any numeric identifier is always less than any 312 /// non-numeric identifier. 313 /// 314 /// Example: `alpha` < `alpha.85` < `alpha.90` < `alpha.200` < `alpha.0a` < `alpha.1a0` < `alpha.a` < `beta` 315 #[derive(Default, Clone, Eq, PartialEq, Hash)] 316 pub struct Prerelease { 317 identifier: Identifier, 318 } 319 320 /// Optional build metadata identifier. This comes after `+` in a SemVer 321 /// version, as in `0.8.1+zstd.1.5.0`. 322 /// 323 /// # Examples 324 /// 325 /// Some real world build metadata idioms drawn from crates.io: 326 /// 327 /// - **[libgit2-sys]** <code>0.12.20+<b>1.1.0</b></code> — for this 328 /// crate, the build metadata indicates the version of the C libgit2 library 329 /// that the Rust crate is built against. 330 /// 331 /// - **[mashup]** <code>0.1.13+<b>deprecated</b></code> — just the word 332 /// "deprecated" for a crate that has been superseded by another. Eventually 333 /// people will take notice of this in Cargo's build output where it lists the 334 /// crates being compiled. 335 /// 336 /// - **[google-bigquery2]** <code>2.0.4+<b>20210327</b></code> — this 337 /// library is automatically generated from an official API schema, and the 338 /// build metadata indicates the date on which that schema was last captured. 339 /// 340 /// - **[fbthrift-git]** <code>0.0.6+<b>c7fcc0e</b></code> — this crate is 341 /// published from snapshots of a big company monorepo. In monorepo 342 /// development, there is no concept of versions, and all downstream code is 343 /// just updated atomically in the same commit that breaking changes to a 344 /// library are landed. Therefore for crates.io purposes, every published 345 /// version must be assumed to be incompatible with the previous. The build 346 /// metadata provides the source control hash of the snapshotted code. 347 /// 348 /// [libgit2-sys]: https://crates.io/crates/libgit2-sys 349 /// [mashup]: https://crates.io/crates/mashup 350 /// [google-bigquery2]: https://crates.io/crates/google-bigquery2 351 /// [fbthrift-git]: https://crates.io/crates/fbthrift-git 352 /// 353 /// # Syntax 354 /// 355 /// Build metadata is a series of dot separated identifiers immediately 356 /// following the patch or pre-release version. Identifiers must comprise only 357 /// ASCII alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must 358 /// not be empty. Leading zeros *are* allowed, unlike any other place in the 359 /// SemVer grammar. 360 /// 361 /// # Total ordering 362 /// 363 /// Build metadata is ignored in evaluating `VersionReq`; it plays no role in 364 /// whether a `Version` matches any one of the comparison operators. 365 /// 366 /// However for comparing build metadatas among one another, they do have a 367 /// total order which is determined by lexicographic ordering of dot-separated 368 /// components. Identifiers consisting of only digits are compared numerically. 369 /// Otherwise, identifiers are compared in ASCII sort order. Any numeric 370 /// identifier is always less than any non-numeric identifier. 371 /// 372 /// Example: `demo` < `demo.85` < `demo.90` < `demo.090` < `demo.200` < `demo.1a0` < `demo.a` < `memo` 373 #[derive(Default, Clone, Eq, PartialEq, Hash)] 374 pub struct BuildMetadata { 375 identifier: Identifier, 376 } 377 378 impl Version { 379 /// Create `Version` with an empty pre-release and build metadata. 380 /// 381 /// Equivalent to: 382 /// 383 /// ``` 384 /// # use semver::{BuildMetadata, Prerelease, Version}; 385 /// # 386 /// # const fn new(major: u64, minor: u64, patch: u64) -> Version { 387 /// Version { 388 /// major, 389 /// minor, 390 /// patch, 391 /// pre: Prerelease::EMPTY, 392 /// build: BuildMetadata::EMPTY, 393 /// } 394 /// # } 395 /// ``` new(major: u64, minor: u64, patch: u64) -> Self396 pub const fn new(major: u64, minor: u64, patch: u64) -> Self { 397 Version { 398 major, 399 minor, 400 patch, 401 pre: Prerelease::EMPTY, 402 build: BuildMetadata::EMPTY, 403 } 404 } 405 406 /// Create `Version` by parsing from string representation. 407 /// 408 /// # Errors 409 /// 410 /// Possible reasons for the parse to fail include: 411 /// 412 /// - `1.0` — too few numeric components. A SemVer version must have 413 /// exactly three. If you are looking at something that has fewer than 414 /// three numbers in it, it's possible it is a `VersionReq` instead (with 415 /// an implicit default `^` comparison operator). 416 /// 417 /// - `1.0.01` — a numeric component has a leading zero. 418 /// 419 /// - `1.0.unknown` — unexpected character in one of the components. 420 /// 421 /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are 422 /// indicated present but empty. 423 /// 424 /// - `1.0.0-alpha_123` — pre-release or build metadata have something 425 /// outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`, 426 /// and `.` (dot). 427 /// 428 /// - `23456789999999999999.0.0` — overflow of a u64. parse(text: &str) -> Result<Self, Error>429 pub fn parse(text: &str) -> Result<Self, Error> { 430 Version::from_str(text) 431 } 432 } 433 434 impl VersionReq { 435 /// A `VersionReq` with no constraint on the version numbers it matches. 436 /// Equivalent to `VersionReq::parse("*").unwrap()`. 437 /// 438 /// In terms of comparators this is equivalent to `>=0.0.0`. 439 /// 440 /// Counterintuitively a `*` VersionReq does not match every possible 441 /// version number. In particular, in order for *any* `VersionReq` to match 442 /// a pre-release version, the `VersionReq` must contain at least one 443 /// `Comparator` that has an explicit major, minor, and patch version 444 /// identical to the pre-release being matched, and that has a nonempty 445 /// pre-release component. Since `*` is not written with an explicit major, 446 /// minor, and patch version, and does not contain a nonempty pre-release 447 /// component, it does not match any pre-release versions. 448 #[cfg(not(no_const_vec_new))] // rustc <1.39 449 pub const STAR: Self = VersionReq { 450 comparators: Vec::new(), 451 }; 452 453 /// Create `VersionReq` by parsing from string representation. 454 /// 455 /// # Errors 456 /// 457 /// Possible reasons for the parse to fail include: 458 /// 459 /// - `>a.b` — unexpected characters in the partial version. 460 /// 461 /// - `@1.0.0` — unrecognized comparison operator. 462 /// 463 /// - `^1.0.0, ` — unexpected end of input. 464 /// 465 /// - `>=1.0 <2.0` — missing comma between comparators. 466 /// 467 /// - `*.*` — unsupported wildcard syntax. parse(text: &str) -> Result<Self, Error>468 pub fn parse(text: &str) -> Result<Self, Error> { 469 VersionReq::from_str(text) 470 } 471 472 /// Evaluate whether the given `Version` satisfies the version requirement 473 /// described by `self`. matches(&self, version: &Version) -> bool474 pub fn matches(&self, version: &Version) -> bool { 475 eval::matches_req(self, version) 476 } 477 } 478 479 impl Comparator { parse(text: &str) -> Result<Self, Error>480 pub fn parse(text: &str) -> Result<Self, Error> { 481 Comparator::from_str(text) 482 } 483 matches(&self, version: &Version) -> bool484 pub fn matches(&self, version: &Version) -> bool { 485 eval::matches_comparator(self, version) 486 } 487 } 488 489 impl Prerelease { 490 pub const EMPTY: Self = Prerelease { 491 identifier: Identifier::empty(), 492 }; 493 new(text: &str) -> Result<Self, Error>494 pub fn new(text: &str) -> Result<Self, Error> { 495 Prerelease::from_str(text) 496 } 497 as_str(&self) -> &str498 pub fn as_str(&self) -> &str { 499 self.identifier.as_str() 500 } 501 is_empty(&self) -> bool502 pub fn is_empty(&self) -> bool { 503 self.identifier.is_empty() 504 } 505 } 506 507 impl BuildMetadata { 508 pub const EMPTY: Self = BuildMetadata { 509 identifier: Identifier::empty(), 510 }; 511 new(text: &str) -> Result<Self, Error>512 pub fn new(text: &str) -> Result<Self, Error> { 513 BuildMetadata::from_str(text) 514 } 515 as_str(&self) -> &str516 pub fn as_str(&self) -> &str { 517 self.identifier.as_str() 518 } 519 is_empty(&self) -> bool520 pub fn is_empty(&self) -> bool { 521 self.identifier.is_empty() 522 } 523 } 524