grust/
quark.rs

1// This file is part of Grust, GObject introspection bindings for Rust
2//
3// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2.1 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
19use types::gchar;
20use util::escape_bytestring;
21
22use glib as ffi;
23
24use std::ffi::CStr;
25use std::fmt;
26use std::sync::atomic;
27
28#[derive(Copy, Clone, Eq, PartialEq)]
29pub struct Quark(ffi::GQuark);
30
31pub struct StaticQuark(pub &'static [u8], pub atomic::AtomicUsize);
32
33impl Quark {
34
35    #[inline]
36    pub unsafe fn from_raw(raw: ffi::GQuark) -> Quark {
37        Quark(raw)
38    }
39
40    pub fn from_static_str(s: &'static str) -> Quark {
41        if !s.ends_with("\0") {
42            panic!("static string is not null-terminated: \"{}\"", s);
43        }
44        unsafe { Quark::from_static_internal(s.as_bytes()) }
45    }
46
47    pub fn from_static_bytes(bytes: &'static [u8]) -> Quark {
48        assert!(!bytes.is_empty());
49        if bytes[bytes.len() - 1] != 0 {
50            panic!("static byte string is not null-terminated: \"{}\"",
51                   escape_bytestring(bytes));
52        }
53        unsafe { Quark::from_static_internal(bytes) }
54    }
55
56    unsafe fn from_static_internal(s: &'static [u8]) -> Quark {
57        let p = s.as_ptr() as *const gchar;
58        let q = ffi::g_quark_from_static_string(p);
59        Quark(q)
60    }
61
62    pub fn to_c_str(&self) -> &'static CStr {
63        let Quark(raw) = *self;
64        unsafe {
65            let s = ffi::g_quark_to_string(raw);
66            CStr::from_ptr(s)
67        }
68    }
69
70    #[inline]
71    pub fn to_bytes(&self) -> &'static [u8] {
72        self.to_c_str().to_bytes()
73    }
74
75    #[inline]
76    pub fn to_raw(&self) -> ffi::GQuark {
77        self.0
78    }
79}
80
81impl fmt::Display for Quark {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        write!(f, "{}", String::from_utf8_lossy(self.to_bytes()))
84    }
85}
86
87impl fmt::Debug for Quark {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        write!(f, "\"{}\"", escape_bytestring(self.to_bytes()))
90    }
91}
92
93impl StaticQuark {
94
95    pub fn get(&self) -> Quark {
96        let StaticQuark(s, ref cached) = *self;
97        let q = cached.load(atomic::Ordering::Relaxed) as ffi::GQuark;
98        if q != 0 {
99            Quark(q)
100        } else {
101            let quark = Quark::from_static_bytes(s);
102            cached.store(quark.to_raw() as usize, atomic::Ordering::Relaxed);
103            quark
104        }
105    }
106}