8000 move CStr8, CStr16, and CString16 from uefi to ucs2 by phip1611 · Pull Request #23 · rust-osdev/ucs2-rs · GitHub
[go: up one dir, main page]

Skip to content

move CStr8, CStr16, and CString16 from uefi to ucs2 #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
types: init basic skeleton and copy chars.rs from uefi-crate
  • Loading branch information
phip1611 committed Jul 30, 2024
commit 80cf03ef05f1c17cb2a9b76cb7685da1380c519c
9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "ucs2"
version = "0.3.3"
authors = ["Gabriel Majeri <gabriel.majeri6@gmail.com>", "Fredrik Aleksander", "Isaac Woods"]
description = "UCS-2 decoding and encoding functions"
version = "0.4.0"
authors = ["The Rust OSDev team"]
description = "UCS-2 decoding and encoding functions as well as convenient types."
repository = "https://github.com/rust-osdev/ucs2-rs"
keywords = ["ucs2", "no-std", "encoding"]
categories = ["encoding", "no-std"]
Expand All @@ -13,3 +13,6 @@ rust-version = "1.56"
[dependencies]
bit_field = "0.10"

[features]
default = []
alloc = []
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@
#![deny(missing_docs)]
#![deny(clippy::all)]

#[cfg(feature = "alloc")]
extern crate alloc;

pub mod encoding;
pub mod types;
186 changes: 186 additions & 0 deletions src/types/chars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//! UEFI character handling
//!
//! UEFI uses both Latin-1 and UCS-2 character encoding, this module implements
//! support for the associated character types.

use core::fmt::{self, Display, Formatter};

/// Character conversion error
#[derive(Clone, Copy, Debug)]
pub struct CharConversionError;

impl Display for CharConversionError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}

#[cfg(feature = "unstable")]
impl core::error::Error for CharConversionError {}

/// A Latin-1 character
#[derive(Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Char8(u8);

impl TryFrom<char> for Char8 {
type Error = CharConversionError;

fn try_from(value: char) -> Result<Self, Self::Error> {
let code_point = u32::from(value);
u8::try_from(code_point)
.map(Char8)
.map_err(|_| CharConversionError)
}
}

impl From<Char8> for char {
fn from(char: Char8) -> Self {
Self::from(char.0)
}
}

impl From<u8> for Char8 {
fn from(value: u8) -> Self {
Self(value)
}
}

impl From<Char8> for u8 {
fn from(char: Char8) -> Self {
char.0
}
}

impl fmt::Debug for Char8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<char as fmt::Debug>::fmt(&From::from(self.0), f)
}
}

impl fmt::Display for Char8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<char as fmt::Display>::fmt(&From::from(self.0), f)
}
}

impl PartialEq<char> for Char8 {
fn eq(&self, other: &char) -> bool {
u32::from(self.0) == u32::from(*other)
}
}

/// Latin-1 version of the NUL character
pub const NUL_8: Char8 = Char8(0);

/// An UCS-2 code point
#[derive(Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Char16(u16);

impl Char16 {
/// Creates a UCS-2 character from a Rust character without checks.
///
/// # Safety
/// The caller must be sure that the character is valid.
#[must_use]
pub const unsafe fn from_u16_unchecked(val: u16) -> Self {
Self(val)
}

/// Checks if the value is within the ASCII range.
#[must_use]
pub const fn is_ascii(&self) -> bool {
self.0 <= 127
}
}

impl TryFrom<char> for Char16 {
type Error = CharConversionError;

fn try_from(value: char) -> Result<Self, Self::Error> {
let code_point = u32::from(value);
u16::try_from(code_point)
.map(Char16)
.map_err(|_| CharConversionError)
}
}

impl From<Char16> for char {
fn from(char: Char16) -> Self {
u32::from(char.0).try_into().unwrap()
}
}

impl TryFrom<u16> for Char16 {
type Error = CharConversionError;

fn try_from(value: u16) -> Result<Self, Self::Error> {
// We leverage char's TryFrom<u32> impl for Unicode validity checking
let res: Result<char, _> = u32::from(value).try_into();
if let Ok(ch) = res {
ch.try_into()
} else {
Err(CharConversionError)
}
}
}

impl From<Char16> for u16 {
fn from(char: Char16) -> Self {
char.0
}
}

impl fmt::Debug for Char16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Ok(c) = u32::from(self.0).try_into() {
<char as fmt::Debug>::fmt(&c, f)
} else {
write!(f, "Char16({:?})", self.0)
}
}
}

impl fmt::Display for Char16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Ok(c) = u32::from(self.0).try_into() {
<char as fmt::Display>::fmt(&c, f)
} else {
write!(f, "{}", core::char::REPLACEMENT_CHARACTER)
}
}
}

impl PartialEq<char> for Char16 {
fn eq(&self, other: &char) -> bool {
u32::from(self.0) == u32::from(*other)
}
}

/// UCS-2 version of the NUL character
pub const NUL_16: Char16 = unsafe { Char16::from_u16_unchecked(0) };

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_char8_from_char() {
assert_eq!(Char8::try_from('A').unwrap(), Char8(0x41));
}

#[test]
fn test_char16_from_char() {
assert_eq!(Char16::try_from('A').unwrap(), Char16(0x41));
assert_eq!(Char16::try_from('ꋃ').unwrap(), Char16(0xa2c3));
}

/// Test that `Char8` and `Char16` can be directly compared with `char`.
#[test]
fn test_char_eq() {
let primitive_char: char = 'A';
assert_eq!(Char8(0x41), primitive_char);
assert_eq!(Char16(0x41), primitive_char);
}
}
Empty file added src/types/cstr16.rs
Empty file.
3 changes: 3 additions & 0 deletions src/types/cstr8.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! Rusty-types to work with UCS-2 strings and for convenient interoperability
//! with Rust string literals (`&str`) and Rust strings (`String`).

9 changes: 9 additions & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

pub(self) mod chars;
mod cstr8;
#[cfg(feature = "alloc")]
mod cstr16;

pub use cstr8::*;
#[cfg(feature = "alloc")]
pub use cstr16::*;
0