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
//! Compact representation of semantic versions as an i32, u32 i64 or u64 //! //! Limitations: //! * Storage format is not standards-conformant (none exists at the time of writing) //! * 32-bit values can represent values in range of `major/minor/patch` = `0 - 1023` (10 bits) //! * 64-bit values can represent values in range of `major/minor/patch` = `0 - 65535` (16 bits) //! * Other than major/minor/patch features (e.g pre-release) are not supported //! //! # Examples //! //! Encode a semver to an integer //! ```rust //! use embedded_semver::Semver; //! //! let version = Semver::new(1, 0, 20); //! //! let int_semver = version.to_i32().unwrap(); //! assert_eq!(int_semver, 83886081); //! assert_eq!(&int_semver.to_le_bytes(), &[0b0000_0001, 0b0000_0000, 0b0000_0000, 0b0000_0101]); //! ``` //! //! Decode an integer into a semver: //! ```rust //! # use embedded_semver::Semver; //! # //! let int_semver: i32 = 83886081; //! //! let version = Semver::from_i32(int_semver).unwrap(); //! assert_eq!(version, Semver::new(1, 0, 20)); //! ``` //! //! # Binary format //! //! * Fields are packed with the most significant bit first (see [Msb0](https://docs.rs/bitvec/0.22.3/bitvec/order/struct.Msb0.html)) //! * Format contains a 2-bit (on 32-bit values) and 4-bit (on 64-bit values) api version, which //! allows for extensibility and/or api changes in future //! //! ## 32 bits //! The binary format for `i32` and `u32` is represented below. Fields: //! //! * `version`: First two bits represent the API version (packed data format). Currenly 0 = V0 //! * `major`: Next 10 bits represent major in range of 0-1023 //! * `minor`: Next 10 bits represent minor in range of 0-1023 //! * `patch`: Next 10 bits represent patch in range of 0-1023 //! //! ```text //! 0 2 12 22 32 //! ├────┴────┼┴┴┴┴┴┴┴┴┴┼┴┴┴┴┴┴┴┴┴┼┴┴┴┴┴┴┴┴┴┤ //! │ API ver │ Major │ Minor │ Patch │ //! │ u2 │ u10 │ u10 │ u10 │ //! └─────────┴─────────┴─────────┴─────────┘ //! ``` //! //! ## 64 bits //! The binary format for `i64` and `u64` is represented below. Fields: //! //! * `version`: First four bits represent the API version (packed data format). Currenly 0 = V0 //! * `major`: Next 16 bits represent major in range of 0-65535 //! * `minor`: Next 16 bits represent minor in range of 0-65535 //! * `patch`: Next 16 bits represent patch in range of 0-65535 //! * 12 remaining bits are unused //! //! ```text //! 0 4 20 36 52 64 //! ├─┴──┴─┴──┼┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┼┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┼┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┼┴┴┴┴┴┴┴┴┴┴┴┤ //! │ API ver │ Major │ Minor │ Patch | (unused) │ //! │ u4 │ u16 │ u16 │ u16 | u12 │ //! └─────────┴───────────────┴─────────────────┴─────────────────┴───────────┘ //! ``` //! //! # Notes about conversions //! //! Note that the binary representations in i32 and i64 are not the same: //! ```rust //! # use embedded_semver::{Semver, Error, Magic}; //! # //! let value: i32 = 16904511; //! //! assert_eq!(Semver::from_i32(value).unwrap(), Semver::new(1023, 1, 5)); //! assert_eq!( //! Semver::from_i64(value as i64).unwrap_err(), //! Error::UnsupportedMagic(Magic::V3) //! ); //! ``` //! //! However, the underlying bits in u32 and i32 represent the same values: //! ```rust //! # use embedded_semver::{Semver, Error}; //! # //! let value: i32 = 16843009; //! let bytes = value.to_le_bytes(); //! //! let i32_value = i32::from_le_bytes(bytes.clone()); //! let u32_value = u32::from_le_bytes(bytes); //! //! assert_eq!(Semver::from_i32(i32_value).unwrap(), Semver::new(1, 1, 5)); //! assert_eq!(Semver::from_u32(u32_value).unwrap(), Semver::new(1, 1, 5)); //! ``` #![cfg_attr(not(feature = "std"), no_std)] pub mod prelude { pub use crate::{Error, Magic, Semver}; } mod error; mod helpers; mod sizes; mod version; pub use error::Error; pub use version::Semver; /// Magic number - storage format /// /// Currently all operations are based on [`Magic::V0`], others are left /// for future extensibility. #[derive(Debug, PartialEq)] pub enum Magic { // can have max 4 (2 bits) V0 = 0, V1 = 1, V2 = 2, V3 = 3, } impl Default for Magic { fn default() -> Self { Magic::V0 } }