# Документация: NevelLibrary.Ulid
## Overview
`NevelLibrary.Ulid` — это высокопроизводительная реализация ULID (Universally Unique Lexicographically Sortable Identifier) для .NET. Тип представляет собой `readonly struct` (значимый тип), который хранит 16 байт данных, состоящих из 48-битного временного метки и 80-битной случайной части.
Ключевые особенности данной реализации:
* **Производительность:** Использует `Unsafe` операции, `Span<T>` и SIMD (если доступно) для минимизации аллокаций памяти.
* **Поддержка кириллицы:** По умолчанию использует расширенный алфавит Base32, включающий кириллические символы (режим `UseCyrillic = true`). Это позволяет генерировать ULID, содержащие буквы русского алфавита.
* **Совместимость:** Реализует интерфейсы `IParsable<Ulid>`, `ISpanParsable<Ulid>`, `IEquatable<Ulid>`, `IComparable<Ulid>`, а также конвертеры для JSON (`System.Text.Json`) и типов.
* **Конвертация:** Поддерживает прямую конвертацию между `Ulid`, `Guid`, `byte[]` и строковым представлением.
---
## Installation
Тип находится в пространстве имен `NevelLibrary.Ulid`. Убедитесь, что ваш проект ссылается на соответствующую библиотеку.
```csharp
using NevelLibrary.Ulid;
```
---
## Основные свойства
| Свойство | Тип | Описание |
| :--- | :--- | :--- |
| `MinValue` | `Ulid` | Минимально возможное значение ULID (timestamp: 1970-01-01, randomness: 0). |
| `MaxValue` | `Ulid` | Максимально возможное значение ULID (timestamp: DateTimeOffset.MaxValue, randomness: 255). |
| `Empty` | `Ulid` | Значение по умолчанию (все байты равны 0). |
| `Time` | `DateTimeOffset` | Извлекает временную метку из ULID. |
| `Randomness` | `byte[]` | Возвращает массив из 10 байт случайной части. |
---
## Создание ULID
### 1. Генерация нового ULID
Метод `NewUlid()` создает уникальный идентификатор на основе текущего времени UTC и криптографически стойкого генератора случайных чисел (`Xoshiro256`).
```csharp
Ulid myUlid = Ulid.NewUlid();
```
### 2. Генерация с фиксированной временной меткой
Если вам нужно создать ULID с конкретной датой (например, для тестирования или восстановления порядка):
```csharp
DateTimeOffset specificTime = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero);
Ulid myUlid = Ulid.NewUlid(specificTime);
```
### 3. Генерация из Guid
Можно преобразовать существующий `Guid` в `Ulid`. Обратите внимание, что это преобразование меняет порядок байт и не гарантирует сохранение временной сортируемости исходного GUID.
```csharp
Guid guid = Guid.NewGuid();
Ulid ulid = (Ulid)guid; // Явное преобразование
// Или
Ulid ulid = Ulid.NewUlid(guid); // Через конструктор (в коде выше конструктор GUID internal, но есть explicit operator)
// В данном коде доступен explicit operator:
Ulid ulidFromGuid = (Ulid)guid;
```
### 4. Создание из массива байт
```csharp
byte[] bytes = new byte[16] { /* 16 байт данных */ };
Ulid ulid = (Ulid)bytes; // Явное преобразование
// Или
Ulid ulid = new Ulid(bytes);
```
---
## Парсинг и преобразование в строку
ULID в `NevelLibrary.Ulid` по умолчанию сериализуется в строку Base32 с использованием **русского алфавита** (если `UseCyrillic` не изменен).
### Парсинг из строки
```csharp
string base32String = "01ARZ3NDEKTSV4RRFFQ69G5FAV"; // Пример (стандартный Base32)
// Для кириллического формата пример строки будет выглядеть иначе, например:
string cyrillicString = "АБВГДЕЖЗИКЛМНПРСТУФХЦЧ...";
if (Ulid.TryParse(cyrillicString, out Ulid result))
{
Console.WriteLine($"Успешно распарсено: {result}");
}
else
{
Console.WriteLine("Ошибка парсинга");
}
```
### Преобразование в строку
```csharp
Ulid ulid = Ulid.NewUlid();
string str = ulid.ToString(); // Возвращает строку Base32
```
> **Важно:** Из-за настройки `UseCyrillic = true`, строковое представление будет содержать русские буквы. Если вам нужно стандартное Base32 (цифры + латиница), необходимо изменить значение `UseCyrillic` на `false` в статическом конструкторе `Ulid` (если это позволяет архитектура вашего проекта) или использовать флаг конфигурации.
---
## Конвертация в другие форматы
### В GUID
```csharp
Ulid ulid = Ulid.NewUlid();
Guid guid = (Guid)ulid; // Явное преобразование
// Или
Guid guid = ulid.ToGuid();
```
### В массив байт
```csharp
Ulid ulid = Ulid.NewUlid();
byte[] bytes = ulid.ToByteArray();
// Или неявное преобразование
byte[] bytesImplicit = ulid;
```
### В Base64
```csharp
Ulid ulid = Ulid.NewUlid();
string base64 = ulid.ToBase64();
```
---
## Сравнение и равенство
`Ulid` реализует `IComparable<Ulid>`, что позволяет сортировать ULID по времени создания (так как timestamp находится в старших битах).
### Проверка равенства
```csharp
Ulid ulid1 = Ulid.NewUlid();
Ulid ulid2 = ulid1;
bool isEqual = ulid1 == ulid2; // true
bool isNotEqual = ulid1 != ulid2; // false
```
### Сравнение
```csharp
Ulid ulidOld = Ulid.NewUlid(new DateTimeOffset(2020, 1, 1, 0, 0, 0, TimeSpan.Zero));
Ulid ulidNew = Ulid.NewUlid(new DateTimeOffset(2023, 1, 1, 0, 0, 0, TimeSpan.Zero));
int comparison = ulidOld.CompareTo(ulidNew);
// comparison < 0, так как ulidOld создан раньше
```
---
## Интеграция с EF Core
Тип реализует интерфейс `IParsable<Ulid>`. Это позволяет Entity Framework Core автоматически преобразовывать строковые значения из базы данных (если столбец хранит ULID как строку) в тип `Ulid`.
Пример использования в модели:
```csharp
public class MyEntity
{
public Ulid Id { get; set; } // EF Core будет использовать IParsable для чтения
public string Name { get; set; }
}
```
---
## JSON сериализация
Тип содержит встроенный `JsonConverter` (`UlidJsonConverter`). При использовании `System.Text.Json` ULID будет сериализован в строку (Base32 формат) и десериализован обратно автоматически.
```csharp
var ulid = Ulid.NewUlid();
var json = JsonSerializer.Serialize(ulid);
// Результат: "АБВГДЕЖЗИКЛМНПРСТУФХЦЧ..." (или латиница, в зависимости от настройки)
var parsedUlid = JsonSerializer.Deserialize<Ulid>(json);
```
---
## Технические детали
### Структура данных
`Ulid` имеет размер 16 байт и.layout `Explicit`:
1. **Timestamp (48 bits):** Первые 6 байт. Представляет количество миллисекунд с эпохи Unix (1970-01-01).
2. **Randomness (80 bits):** Последние 10 байт. Генерируется с помощью `Xoshiro256`.
### Алфавит Base32
По умолчанию используется следующий алфавит (кириллица):
`АБВГДЕЖЗИКЛМНПРСТУФХЦЧ` + `0123456789`
Если `UseCyrillic` установлен в `false`, используется стандартный алфавит:
`ABCDEFGHJKMNPQRSTVWXYZ` + `0123456789`
### Производительность
* Используется `ArrayPool<byte>` для временных буферов при конвертации в Base64.
* Операции с памятью выполняются через `Unsafe` и `Span` для избежания границ проверок и аллокаций.
* Поддержка `Vector128` (SIMD) для ускоренной конвертации между `Guid` и `Ulid` на поддерживаемых платформах.
---
## FAQ
**Q: Почему мой ULID содержит русские буквы?**
A: По умолчанию в коде `NevelLibrary.Ulid` установлена константа `UseCyrillic = true`. Это уникальная особенность данной библиотеки. Если вам нужен стандартный Base32, проверьте возможность изменения этой константы или использование альтернативной реализации.
**Q: Можно ли безопасно сравнивать ULID из разных систем?**
A: Да, если они используют одинаковый алфавит Base32 и порядок байт. Однако, если одна система использует кириллический алфавит, а другая стандартный, строковые представления будут несовместимы, хотя бинарное представление (16 байт) может быть одинаковым для одного и того же ULID.
**Q: Как получить timestamp из ULID?**
A: Используйте свойство `Time`:
```csharp
DateTimeOffset time = myUlid.Time;
```
ULID нейронка
Первый тестовый
ЖУРНАЛ_ОБСУЖДЕНИЙ: 0
[УВЕДОМЛЕНИЕ]
Пусто
Комментарии не найдены.
ДОСТУП_ОГРАНИЧЕН
Требуется авторизация для передачи данных в канал.