fontconfig_cache_parser/data.rs
1//! Definitions of fontconfig's raw serialized format.
2//!
3//! Fontconfig's cache format is defined by writing out C structs byte-for-byte.
4//! This module gives a rust definition for some of those structs (more may be
5//! supported in the future). Since the fontconfig structs include offsets to other
6//! structs, you cannot do much with the raw data itself: you need to interpret
7//! that data in the context of its location in the cache. See the [`ptr`](crate::ptr)
8//! module for more details.
9//!
10//! In any case, you are unlikely to need access to the raw serialized format, as this
11//! crate defines more convenient wrappers around this raw format.
12
13use bytemuck::AnyBitPattern;
14use std::os::raw::{c_int, c_uint};
15
16use crate::{
17 ptr::{Offset, PtrOffset},
18 CharSetLeaf,
19};
20
21/// The fontconfig cache header, in the raw serialized format.
22#[derive(AnyBitPattern, Copy, Clone, Debug)]
23#[repr(C)]
24pub struct CacheData {
25 /// The magic 4 bytes marking the data as a fontconfig cache.
26 pub magic: c_uint,
27 /// The cache format version. We support versions 7 and 8.
28 pub version: c_int,
29 /// The size of the cache.
30 pub size: isize,
31 /// This cache caches the data of all fonts in some directory.
32 /// Here is (an offset to) the name of that directory.
33 pub dir: Offset<u8>,
34 /// Here is an offset to an array of offsets to the names of
35 /// subdirectories.
36 pub dirs: Offset<Offset<u8>>,
37 /// How many subdirectories are there?
38 pub dirs_count: c_int,
39 /// An offset to the set of fonts in this cache.
40 pub set: Offset<FontSetData>,
41 /// A "checksum" of this cache (but really just a timestamp).
42 pub checksum: c_int,
43 /// Another "checksum" of this cache (but really just a more precise timestamp).
44 pub checksum_nano: c_int,
45}
46
47/// A set of fonts, in the raw serialized format.
48#[derive(AnyBitPattern, Copy, Clone, Debug)]
49#[repr(C)]
50pub struct FontSetData {
51 /// The number of fonts in this set.
52 pub nfont: c_int,
53 // Capacity of the font array. Uninteresting for the serialized format.
54 _sfont: c_int,
55 /// Pointer to an array of fonts.
56 ///
57 /// All the offsets here (both outer and inner) are relative to this `FontSetData`.
58 pub fonts: PtrOffset<PtrOffset<PatternData>>,
59}
60
61/// The raw serialized format of a [`Pattern`](crate::Pattern).
62#[derive(AnyBitPattern, Copy, Clone, Debug)]
63#[repr(C)]
64pub struct PatternData {
65 /// The number of elements in this pattern.
66 pub num: c_int,
67 // The capacity of the elements array. For serialized data, it's probably
68 // the same as `num`.
69 _size: c_int,
70 /// The offset of the element array.
71 pub elts_offset: Offset<PatternEltData>,
72 ref_count: c_int,
73}
74
75/// A single element of a [`Pattern`](crate::Pattern), in the raw serialized format.
76#[derive(AnyBitPattern, Copy, Clone, Debug)]
77#[repr(C)]
78pub struct PatternEltData {
79 /// The object type tag.
80 pub object: c_int,
81 /// Offset of the linked list of values.
82 pub values: PtrOffset<ValueListData>,
83}
84
85/// A linked list of [`Value`](crate::Value)s, in the raw serialized format.
86#[derive(AnyBitPattern, Copy, Clone, Debug)]
87#[repr(C)]
88pub struct ValueListData {
89 /// An offset to the next element in the linked list.
90 pub next: PtrOffset<ValueListData>,
91 /// The value of the current list element.
92 pub value: ValueData,
93 binding: c_int,
94}
95
96/// Fontconfig's `FcValue` data type, in the raw serialized format.
97#[derive(AnyBitPattern, Copy, Clone)]
98#[repr(C)]
99pub struct ValueData {
100 /// The value's type tag.
101 pub ty: c_int,
102 /// The value's value.
103 pub val: ValueUnion,
104}
105
106impl std::fmt::Debug for ValueData {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 f.write_fmt(format_args!("{}", self.ty))
109 // TODO: write the rest
110 }
111}
112
113/// A dynamically typed value, as a raw union.
114///
115/// Many of fontconfig's values are stored as a tagged union. But because
116/// there's no layout guarantees for tagged unions in rust, we read them
117/// in the C layout, as a combination of `c_int` tag and an untagged union.
118///
119/// This is the untagged union part.
120#[repr(C)]
121#[derive(AnyBitPattern, Copy, Clone)]
122#[allow(missing_docs)]
123pub union ValueUnion {
124 pub s: PtrOffset<u8>,
125 pub i: c_int,
126 pub b: c_int,
127 pub d: f64,
128 pub m: PtrOffset<()>, // TODO
129 pub c: PtrOffset<CharSetData>,
130 pub f: PtrOffset<()>,
131 pub l: PtrOffset<()>, // TODO
132 pub r: PtrOffset<()>, // TODO
133}
134
135/// A set of code points, in the raw serialized format.
136///
137/// # Implementation details
138///
139/// This charset is implemented as a bunch of bitsets. Each bitset (a [`CharSetLeaf`](crate::CharSetLeaf))
140/// has 256 bits, and so it represents the least significant byte of the codepoint. Associated to each
141/// leaf is a 16-bit offset, representing the next two least-significant bytes of the codepoint.
142/// (In particular, this can represent any subset of the numbers `0` through `0x00FFFFFF`, which is
143/// big enough for the unicode range.)
144#[derive(AnyBitPattern, Copy, Clone, Debug)]
145#[repr(C)]
146pub struct CharSetData {
147 // Reference count. Not interesting for us.
148 ref_count: c_int,
149 /// Length of both of the following arrays
150 pub num: c_int,
151 /// Array of offsets to leaves. Each offset is relative to the start of the array, not the
152 /// start of this struct!
153 pub leaves: Offset<Offset<CharSetLeaf>>,
154 /// Array having the same length as `leaves`, and storing the 16-bit offsets of each leaf.
155 pub numbers: Offset<u16>,
156}