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
123
124
// Copyright (C) 2026 Dylan Jones
// SPDX-License-Identifier: GPL-3.0-only
//! Directory naming for analysis and artwork files in rekordbox's shared storage.
//!
//! USB analysis directories are derived from the exported audio path using a
//! 32-bit hash. Local directories use a UUID split into two path components.
//! The public helpers return forward-slash paths with a leading `/PIONEER/`,
//! without a filename or trailing slash. They only construct strings and do not
//! inspect or create directories.
//!
//! Resolve USB paths beneath the USB volume root and local paths beneath the
//! configured analysis/share root. Remove the leading slash before joining to
//! a filesystem root so that the returned path does not replace that root.
use Uuid;
/// Compute the USB directory selector and reduced hash for an exported audio path.
///
/// `track_path` is relative to the USB volume root, with a leading slash, such as
/// `/Contents/Artist/Track.flac`. The text is processed exactly as supplied,
/// without changing case, separators, or Unicode normalization and without
/// appending a NUL terminator.
///
/// Starting at zero, the accumulator processes each UTF-16 code unit with two
/// multiply-add rounds: `hash * 0x5BC9 + unit`, then `hash * 0x93B5 + unit`.
/// Each round wraps modulo 2^32. Non-BMP characters contribute both surrogate
/// code units. The final accumulator is reduced modulo 200003 (`0x30D43`).
///
/// Returns `(p, h)`, where `h` is the reduced hash and `p` packs bits
/// 0, 2, 6, 7, 9, 13, and 16 of `h` into bits 0 through 6, respectively.
/// Thus `p` is in `0..=127` and `h` is in `0..200003`. The hash can collide;
/// this helper does not resolve collisions.
/// Format the two USB directory components as `P{p:03X}/{h:08X}`.
///
/// The selector and reduced hash use uppercase, zero-padded hexadecimal.
/// The result has no leading or trailing slash. Input handling is described in
/// [`compute_usb_share_path_hash`].
/// Format a UUID as the two directory components used by local shared storage.
///
/// Parsing normalizes the UUID to lowercase hyphenated text. The first three
/// characters form the first directory and the remaining 33 form the second,
/// preserving the hyphens. For example, `0e80d4cc-06a6-4574-ba18-1c2301ea9924`
/// becomes `0e8/0d4cc-06a6-4574-ba18-1c2301ea9924`.
///
/// # Panics
///
/// Panics if `uuid` cannot be parsed as a UUID.
/// Return the ANLZ directory for an audio file exported to a USB volume.
///
/// `track_path` must be the exported audio path relative to the volume root,
/// including its leading slash, for example `/Contents/Artist/Track.flac`.
/// It is hashed as supplied; this function does not normalize the input or
/// validate that it points to an exported file.
///
/// The result has the form `/PIONEER/USBANLZ/Pxxx/hhhhhhhh`, with uppercase
/// hexadecimal directory names. Append an analysis filename such as
/// `ANLZ0000.DAT`, `ANLZ0000.EXT`, or `ANLZ0000.2EX` as needed.
/// Return the local ANLZ directory derived from a track's `djmdContent.UUID`.
///
/// The UUID is normalized to lowercase hyphenated text and split after three
/// characters beneath `/PIONEER/USBANLZ/`. Resolve the result relative to the
/// configured analysis/share root, then append the required ANLZ filename.
/// For existing tracks, the stored `AnalysisDataPath` remains authoritative.
///
/// # Panics
///
/// Panics if `uuid` cannot be parsed as a UUID.
/// Return the local artwork directory derived from the supplied UUID.
///
/// The UUID is normalized to lowercase hyphenated text and split after three
/// characters beneath `/PIONEER/Artwork/`, using the same directory layout as
/// local analysis files. The result identifies a directory, not an image file;
/// the caller supplies the artwork UUID and chooses the filename separately.
///
/// # Panics
///
/// Panics if `uuid` cannot be parsed as a UUID.