mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-13 21:51:04 +00:00
Merge pull request #824 from alexcrichton/osstr-osstring
Implement Serialize/Deserialize for OsStr/OsString
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- APPVEYOR_RUST_CHANNEL: stable
|
||||||
|
- APPVEYOR_RUST_CHANNEL: nightly
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Install rust, x86_64-pc-windows-msvc host
|
||||||
|
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||||
|
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
|
||||||
|
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
|
||||||
|
- rustc -vV
|
||||||
|
- cargo -vV
|
||||||
|
|
||||||
|
build: false
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- sh -c 'PATH=`rustc --print sysroot`/bin:$PATH ./travis.sh'
|
||||||
+106
-1
@@ -26,7 +26,7 @@ use std::net;
|
|||||||
use std::path;
|
use std::path;
|
||||||
use core::str;
|
use core::str;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::ffi::CString;
|
use std::ffi::{CString, OsString};
|
||||||
#[cfg(all(feature = "std", feature="unstable"))]
|
#[cfg(all(feature = "std", feature="unstable"))]
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
|
||||||
@@ -910,6 +910,7 @@ impl Visitor for PathBufVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for path::PathBuf {
|
impl Deserialize for path::PathBuf {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<path::PathBuf, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<path::PathBuf, D::Error>
|
||||||
@@ -921,6 +922,110 @@ impl Deserialize for path::PathBuf {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
enum OsStringKind {
|
||||||
|
Unix,
|
||||||
|
Windows,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
static OSSTR_VARIANTS: &'static [&'static str] = &["Unix", "Windows"];
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
impl Deserialize for OsStringKind {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<OsStringKind, D::Error>
|
||||||
|
where D: Deserializer
|
||||||
|
{
|
||||||
|
struct KindVisitor;
|
||||||
|
|
||||||
|
impl Visitor for KindVisitor {
|
||||||
|
type Value = OsStringKind;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("`Unix` or `Windows`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u32<E>(self, value: u32) -> Result<OsStringKind, E>
|
||||||
|
where E: Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
0 => Ok(OsStringKind::Unix),
|
||||||
|
1 => Ok(OsStringKind::Windows),
|
||||||
|
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<OsStringKind, E>
|
||||||
|
where E: Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
"Unix" => Ok(OsStringKind::Unix),
|
||||||
|
"Windows" => Ok(OsStringKind::Windows),
|
||||||
|
_ => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, value: &[u8]) -> Result<OsStringKind, E>
|
||||||
|
where E: Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
b"Unix" => Ok(OsStringKind::Unix),
|
||||||
|
b"Windows" => Ok(OsStringKind::Windows),
|
||||||
|
_ => {
|
||||||
|
match str::from_utf8(value) {
|
||||||
|
Ok(value) => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
|
||||||
|
Err(_) => {
|
||||||
|
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize(KindVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
struct OsStringVisitor;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
impl Visitor for OsStringVisitor {
|
||||||
|
type Value = OsString;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("os string")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn visit_enum<V>(self, visitor: V) -> Result<OsString, V::Error>
|
||||||
|
where V: EnumVisitor,
|
||||||
|
{
|
||||||
|
use std::os::unix::ffi::OsStringExt;
|
||||||
|
|
||||||
|
match try!(visitor.visit_variant()) {
|
||||||
|
(OsStringKind::Unix, variant) => {
|
||||||
|
variant.visit_newtype().map(OsString::from_vec)
|
||||||
|
}
|
||||||
|
(OsStringKind::Windows, _) => {
|
||||||
|
Err(Error::custom("cannot deserialize windows os string on unix"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
impl Deserialize for OsString {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error>
|
||||||
|
where D: Deserializer
|
||||||
|
{
|
||||||
|
deserializer.deserialize_enum("OsString", OSSTR_VARIANTS, OsStringVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T: Deserialize> Deserialize for Box<T> {
|
impl<T: Deserialize> Deserialize for Box<T> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
|
||||||
|
|||||||
+36
-1
@@ -20,7 +20,7 @@ use core::ops;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::path;
|
use std::path;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::{CString, CStr, OsString, OsStr};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
@@ -714,6 +714,41 @@ impl Serialize for path::PathBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
impl Serialize for OsStr {
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
serializer.serialize_newtype_variant("OsString",
|
||||||
|
0,
|
||||||
|
"Unix",
|
||||||
|
self.as_bytes())
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
use std::os::windows::ffi::OsStrExt;
|
||||||
|
let val = self.encode_wide().collect::<Vec<_>>();
|
||||||
|
serializer.serialize_newtype_variant("OsString",
|
||||||
|
1,
|
||||||
|
"Windows",
|
||||||
|
&val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Serialize for OsString {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
self.as_os_str().serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
impl<T> Serialize for NonZero<T>
|
impl<T> Serialize for NonZero<T>
|
||||||
where T: Serialize + Zeroable
|
where T: Serialize + Zeroable
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#![feature(lang_items, start, libc)]
|
#![feature(lang_items, start, libc, compiler_builtins_lib)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
extern crate compiler_builtins;
|
||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::net;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ffi::CString;
|
use std::ffi::{CString, OsString};
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
@@ -913,6 +913,56 @@ declare_tests! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[test]
|
||||||
|
fn test_osstring() {
|
||||||
|
use std::os::unix::ffi::OsStringExt;
|
||||||
|
|
||||||
|
let value = OsString::from_vec(vec![1, 2, 3]);
|
||||||
|
let tokens = [
|
||||||
|
Token::EnumStart("OsString"),
|
||||||
|
Token::Str("Unix"),
|
||||||
|
Token::SeqStart(Some(2)),
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U8(1),
|
||||||
|
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U8(2),
|
||||||
|
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U8(3),
|
||||||
|
Token::SeqEnd,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_de_tokens(&value, &tokens);
|
||||||
|
assert_de_tokens_ignore(&tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[test]
|
||||||
|
fn test_osstring() {
|
||||||
|
use std::os::windows::ffi::OsStringExt;
|
||||||
|
|
||||||
|
let value = OsString::from_wide(&[1, 2, 3]);
|
||||||
|
let tokens = [
|
||||||
|
Token::EnumStart("OsString"),
|
||||||
|
Token::Str("Windows"),
|
||||||
|
Token::SeqStart(Some(2)),
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U16(1),
|
||||||
|
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U16(2),
|
||||||
|
|
||||||
|
Token::SeqSep,
|
||||||
|
Token::U16(3),
|
||||||
|
Token::SeqEnd,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_de_tokens(&value, &tokens);
|
||||||
|
assert_de_tokens_ignore(&tokens);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cstr() {
|
fn test_cstr() {
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ fn test_net_ipaddr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
fn test_cannot_serialize_paths() {
|
fn test_cannot_serialize_paths() {
|
||||||
let path = unsafe {
|
let path = unsafe {
|
||||||
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
|
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ channel() {
|
|||||||
pwd
|
pwd
|
||||||
(set -x; cargo "$@")
|
(set -x; cargo "$@")
|
||||||
fi
|
fi
|
||||||
|
elif [ -n "${APPVEYOR}" ]; then
|
||||||
|
if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then
|
||||||
|
pwd
|
||||||
|
(set -x; cargo "$@")
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
pwd
|
pwd
|
||||||
(set -x; cargo "+${CHANNEL}" "$@")
|
(set -x; cargo "+${CHANNEL}" "$@")
|
||||||
|
|||||||
Reference in New Issue
Block a user