Skip to content

Commit 39e6213

Browse files
authored
Merge pull request #9 from csssuf/unicode-utils
util: add utf16/utf8 utility functions
2 parents 4b70566 + 2ad92d2 commit 39e6213

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod runtimeservices;
1212
mod console;
1313
mod task;
1414
mod event;
15+
pub mod util;
1516

1617

1718
pub use base::{Handle, Handles, Event, MemoryType, Status, Time};

src/util/mod.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2017 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
use core::slice;
15+
use core::str;
16+
17+
use base::Status;
18+
19+
/// Take a null-terminated UTF-16 string (such as one returned by EFI functions) and determine its
20+
/// length.
21+
pub fn utf16_strlen(c: *const u16) -> usize {
22+
let mut len: usize = 0;
23+
24+
unsafe {
25+
while *(c.offset(len as isize)) != 0 {
26+
len += 1;
27+
}
28+
}
29+
30+
len
31+
}
32+
33+
/// Convert a raw pointer to a UTF-16 string to a rust &str.
34+
/// Note: This function expects to receive a fully ASCII-compatible string. If it does not, it will
35+
/// fail.
36+
pub fn utf16_ptr_to_str(chars: *const u16) -> Result<&'static str, Status> {
37+
let strlen = utf16_strlen(chars);
38+
39+
let raw_u8_ptr: Result<*mut u8, Status> = ::get_system_table().boot_services().allocate_pool(strlen);
40+
if let Err(status) = raw_u8_ptr {
41+
return Err(status);
42+
}
43+
let raw_u8_ptr = raw_u8_ptr.unwrap();
44+
45+
for i in 0..strlen as isize {
46+
unsafe {
47+
// If the character is not ASCII, fail.
48+
if *(chars.offset(i)) >= 128 {
49+
::get_system_table().boot_services().free_pool(raw_u8_ptr);
50+
return Err(Status::InvalidParameter);
51+
}
52+
53+
*(raw_u8_ptr.offset(i)) = *(chars.offset(i)) as u8;
54+
}
55+
}
56+
57+
let u8_slice = unsafe { slice::from_raw_parts(raw_u8_ptr, strlen) };
58+
unsafe {
59+
Ok(str::from_utf8_unchecked(u8_slice))
60+
}
61+
}
62+
63+
/// Convert a rust &str to a pointer to a UTF-16 string.
64+
/// Note: This function expects to receive a fully ASCII-compatible string. If it does not, it will
65+
/// fail.
66+
pub fn str_to_utf16_ptr(chars: &str) -> Result<*const u16, Status> {
67+
::get_system_table()
68+
.boot_services()
69+
.allocate_pool(chars.len() + 1)
70+
.and_then(|u16_ptr| {
71+
for (i, c) in chars.chars().enumerate() {
72+
if c.len_utf8() > 1 {
73+
::get_system_table().boot_services().free_pool(u16_ptr);
74+
return Err(Status::Unsupported);
75+
}
76+
77+
unsafe {
78+
*(u16_ptr.offset(i as isize)) = c as u16;
79+
}
80+
}
81+
unsafe { *(u16_ptr.offset(chars.len() as isize)) = 0 };
82+
83+
Ok(u16_ptr as *const u16)
84+
})
85+
}

0 commit comments

Comments
 (0)