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
// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013-2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use glib as ffi;
use types::{gchar,gpointer};

use libc;
use std::ffi::{CStr, CString, NulError};
use std::mem;
use std::ops::Deref;
use std::str;

pub struct OwnedGStr {
    ptr: *const gchar,
}

impl OwnedGStr {

    pub unsafe fn from_ptr(ptr: *mut gchar) -> OwnedGStr {
        OwnedGStr { ptr: ptr }
    }
}

impl Deref for OwnedGStr {

    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { CStr::from_ptr(self.ptr) }
    }
}

impl Drop for OwnedGStr {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.ptr as gpointer) }
    }
}

impl Clone for OwnedGStr {
    fn clone(&self) -> OwnedGStr {
        unsafe {
            OwnedGStr::from_ptr(ffi::g_strdup(self.ptr))
        }
    }
}

impl PartialEq for OwnedGStr {
    fn eq(&self, other: &OwnedGStr) -> bool {
        unsafe { libc::strcmp(self.ptr, other.ptr) == 0 }
    }
}

impl Eq for OwnedGStr { }

pub struct Utf8 {
    inner: CStr
}

impl Utf8 {

    #[inline]
    pub fn as_ptr(&self) -> *const gchar {
        self.inner.as_ptr()
    }

    #[inline]
    pub fn to_str(&self) -> &str {
        unsafe { str::from_utf8_unchecked(self.inner.to_bytes()) }
    }

    pub fn from_static_str(s: &'static str) -> &'static Utf8 {
        assert!(s.ends_with("\0"),
                "static string is not null-terminated: \"{}\"", s);
        unsafe { Utf8::from_ptr(s.as_ptr() as *const gchar) }
    }

    pub unsafe fn from_ptr<'a>(ptr: *const gchar) -> &'a Utf8 {
        mem::transmute(CStr::from_ptr(ptr))
    }
}

impl AsRef<CStr> for Utf8 {
    #[inline]
    fn as_ref(&self) -> &CStr { &self.inner }
}

pub struct Utf8String {
    inner: CString
}

impl Deref for Utf8String {

    type Target = Utf8;

    fn deref(&self) -> &Utf8 {
        unsafe { Utf8::from_ptr(self.inner.as_ptr()) }
    }
}

impl Utf8String {
    pub fn new<T>(t: T) -> Result<Utf8String, NulError>
        where T: Into<String>
    {
        let c_str = try!(CString::new(t.into()));
        Ok(Utf8String { inner: c_str })
    }
}