Skip to content

Commit

Permalink
Merge pull request #7 from flaviojs/support_more_std_types
Browse files Browse the repository at this point in the history
Support more std types
  • Loading branch information
tjol authored May 31, 2024
2 parents b89225e + 72f1a85 commit df8ee22
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
58 changes: 55 additions & 3 deletions src/format.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::convert::{TryFrom, TryInto};
use std::ffi::{CStr, CString};

use crate::{
parser::{ConversionSpecifier, ConversionType, NumericParam},
Expand Down Expand Up @@ -162,7 +163,16 @@ impl Printf for i32 {

impl Printf for u32 {
fn format(&self, spec: &ConversionSpecifier) -> Result<String> {
(*self as u64).format(spec)
match spec.conversion_type {
ConversionType::Char => {
if let Some(c) = char::from_u32(*self) {
c.format(spec)
} else {
Err(PrintfError::WrongType)
}
}
_ => (*self as u64).format(spec),
}
}
fn as_int(&self) -> Option<i32> {
i32::try_from(*self).ok()
Expand All @@ -188,7 +198,16 @@ impl Printf for i16 {

impl Printf for u16 {
fn format(&self, spec: &ConversionSpecifier) -> Result<String> {
(*self as u64).format(spec)
match spec.conversion_type {
ConversionType::Char => {
if let Some(Ok(c)) = char::decode_utf16([*self]).next() {
c.format(spec)
} else {
Err(PrintfError::WrongType)
}
}
_ => (*self as u64).format(spec),
}
}
fn as_int(&self) -> Option<i32> {
Some(*self as i32)
Expand All @@ -204,6 +223,8 @@ impl Printf for i8 {
ConversionType::HexIntLower | ConversionType::HexIntUpper | ConversionType::OctInt => {
(*self as u8).format(spec)
}
// c_char
ConversionType::Char => (*self as u8).format(spec),
_ => Err(PrintfError::WrongType),
}
}
Expand All @@ -214,7 +235,16 @@ impl Printf for i8 {

impl Printf for u8 {
fn format(&self, spec: &ConversionSpecifier) -> Result<String> {
(*self as u64).format(spec)
match spec.conversion_type {
ConversionType::Char => {
if self.is_ascii() {
char::from(*self).format(spec)
} else {
Err(PrintfError::WrongType)
}
}
_ => (*self as u64).format(spec),
}
}
fn as_int(&self) -> Option<i32> {
Some(*self as i32)
Expand Down Expand Up @@ -475,3 +505,25 @@ impl Printf for String {
None
}
}

impl Printf for &CStr {
fn format(&self, spec: &ConversionSpecifier) -> Result<String> {
if let Ok(s) = self.to_str() {
s.format(spec)
} else {
Err(PrintfError::WrongType)
}
}
fn as_int(&self) -> Option<i32> {
None
}
}

impl Printf for CString {
fn format(&self, spec: &ConversionSpecifier) -> Result<String> {
self.as_c_str().format(spec)
}
fn as_int(&self) -> Option<i32> {
None
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use parser::{parse_format_string, FormatElement};
pub use parser::{ConversionSpecifier, ConversionType, NumericParam};

/// Error type
#[derive(Debug, Clone, Copy, Error)]
#[derive(Debug, Clone, Copy, Error, PartialEq, Eq)]
pub enum PrintfError {
/// Error parsing the format string
#[error("Error parsing the format string")]
Expand Down
22 changes: 21 additions & 1 deletion tests/compare_to_libc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// The libc crate on Windows doesn't have snprintf
#![cfg(not(windows))]

use std::convert::TryInto;
use std::convert::{TryFrom, TryInto};
use std::ffi::CString;
use std::os::raw::c_char;

Expand Down Expand Up @@ -112,4 +112,24 @@ fn test_float() {
fn test_str() {
check_fmt_s("test %% with string: %s yay\n", "FOO");
check_fmt("test char %c", '~');
let c_string = CString::new("test").unwrap();
check_fmt("%s", c_string.as_c_str());
check_fmt("%s", c_string);
}

#[test]
fn test_char() {
check_fmt("%c", 'x');
check_fmt("%c", b'x');
check_fmt("%c", b'x' as c_char);
check_fmt("%c", u16::try_from('x').unwrap());
check_fmt("%c", u32::try_from('x').unwrap());
}

#[test]
fn test_sanity() {
// u8 must not misinterpret bytes from multi-byte UTF-8 characters
let bytes = "∆".as_bytes();
assert!(bytes.len() > 1);
assert_eq!(sprintf!("%c", bytes[0]), Err(PrintfError::WrongType));
}

0 comments on commit df8ee22

Please sign in to comment.