v4 / vlib / v / embed_file / embed_file.v
104 lines · 96 sloc · 2.91 KB · 83fd036a98cc7d2e91992898416169f47329240f
Raw
1module embed_file
2
3// EmbedFileData encapsulates functionality for the `$embed_file()` compile time call.
4pub struct EmbedFileData {
5 apath string
6 compression_type string
7mut:
8 compressed &u8 = unsafe { nil }
9 compressed_len int
10 uncompressed &u8 = unsafe { nil }
11 free_compressed bool
12 free_uncompressed bool
13pub:
14 len int
15 path string
16}
17
18pub fn (ed EmbedFileData) str() string {
19 return 'embed_file.EmbedFileData{ len: ${ed.len}, path: "${ed.path}", apath: "${ed.apath}", uncompressed: ${ptr_str(ed.uncompressed)} }'
20}
21
22@[unsafe]
23pub fn (mut ed EmbedFileData) free() {
24 unsafe {
25 ed.path.free()
26 ed.apath.free()
27 ed.compression_type.free()
28 if ed.free_compressed {
29 free(ed.compressed)
30 ed.compressed = &u8(nil)
31 }
32 if ed.free_uncompressed {
33 free(ed.uncompressed)
34 ed.uncompressed = &u8(nil)
35 }
36 }
37}
38
39pub fn (original &EmbedFileData) to_string() string {
40 unsafe {
41 mut ed := &EmbedFileData(original)
42 the_copy := &u8(memdup(ed.data(), ed.len))
43 return the_copy.vstring_with_len(ed.len)
44 }
45}
46
47pub fn (original &EmbedFileData) to_bytes() []u8 {
48 unsafe {
49 mut ed := &EmbedFileData(original)
50 the_copy := memdup(ed.data(), ed.len)
51 return the_copy.vbytes(ed.len)
52 }
53}
54
55pub fn (mut ed EmbedFileData) data() &u8 {
56 if ed.uncompressed != unsafe { nil } {
57 return ed.uncompressed
58 }
59 if ed.uncompressed == unsafe { nil } && ed.compressed != unsafe { nil } {
60 decoder := g_embed_file_decoders.decoders[ed.compression_type] or {
61 panic('EmbedFileData error: unknown compression of "${ed.path}": "${ed.compression_type}"')
62 }
63 compressed := unsafe { ed.compressed.vbytes(ed.compressed_len) }
64 decompressed := decoder.decompress(compressed) or {
65 panic('EmbedFileData error: decompression of "${ed.path}" failed: ${err}')
66 }
67 unsafe {
68 ed.uncompressed = &u8(memdup(decompressed.data, ed.len))
69 }
70 } else {
71 $if !freestanding {
72 reload_from_file_at_runtime(mut ed)
73 }
74 }
75 return ed.uncompressed
76}
77
78//////////////////////////////////////////////////////////////////////////////
79// EmbedFileIndexEntry is used internally by the V compiler when you compile a
80// program that uses $embed_file('file.bin') in -prod mode.
81// V will generate a static index of all embedded files, and will call the
82// find_index_entry_by_path over the index and the relative paths of the embeds.
83// Note: these are public on purpose, to help -usecache.
84pub struct EmbedFileIndexEntry {
85 id int
86 path string
87 algo string
88 data &u8 = unsafe { nil }
89}
90
91// find_index_entry_by_path is used internally by the V compiler:
92@[markused]
93pub fn find_index_entry_by_path(start voidptr, path string, algo string) &EmbedFileIndexEntry {
94 unsafe {
95 mut x := &EmbedFileIndexEntry(start)
96 for x.id >= 0 && x.data != 0 && (x.algo != algo || x.path != path) {
97 x++
98 }
99 $if trace_embed_file ? {
100 eprintln('>> v.embed_file find_index_entry_by_path ${ptr_str(start)}, id: ${x.id}, path: "${path}", algo: "${algo}" => ${ptr_str(x)}')
101 }
102 return x
103 }
104}
105