# 21. Strings, Unicode et encodages ## 21.1 `String` — V1 REQUIS — FIGÉ EN PRINCIPE `String` est le type ordinaire de texte Unicode au niveau sémantique. Sa valeur observable est une séquence de Unicode scalar values. La représentation physique interne peut varier suivant le backend/target, sans devenir observable via l'API sémantique de `String`. `String` est mutable par défaut lorsque son API expose des opérations mutantes contrôlées. ```text String text = "abc"; text::append("def"); // OK ``` Un accès `const String` interdit les mutations via cet accès selon les règles générales de `const`. ## 21.2 `char` — V1 REQUIS — FIGÉ `char` représente exactement un Unicode scalar value, et non un octet, une unité UTF-8/UTF-16 ou un grapheme utilisateur complet. Exemples valides : ```text 'A' 'é' '中' '😀' '\n' '\u{1F600}' ``` Après traitement des escapes, un littéral `char` doit contenir exactement un scalar. Saselang n'effectue aucune normalisation Unicode implicite. ## 21.3 Types encodés Core — V1 REQUIS — DIRECTION FIGÉE Le Core fournit les types encodés explicites : ```text Utf8Char Utf16Char Utf32Char Utf8String Utf16String Utf32String ``` Ils ne sont ni des alias ni des sous-classes de `String`/`char`. Ils expriment explicitement l'encodage utilisé. ```text Utf8Char exactement un Unicode scalar encodé en UTF-8 1 à 4 uint8 Utf16Char exactement un Unicode scalar encodé en UTF-16 1 à 2 uint16 Utf32Char exactement un Unicode scalar encodé en UTF-32 1 uint32 ``` ```text Utf8String séquence UTF-8 valide Utf16String séquence UTF-16 valide Utf32String séquence UTF-32 valide ``` Toute valeur de ces types maintient son invariant d'encodage. Les code units brutes restent : ```text UTF-8 -> uint8 UTF-16 -> uint16 UTF-32 -> uint32 ``` Aucun `Utf8CodeUnit` / `Utf16CodeUnit` / `Utf32CodeUnit` distinct n'est introduit tant qu'un besoin sémantique réel n'est pas démontré. ## 21.4 Conversions Unicode — V1 REQUIS — FIGÉ EN PRINCIPE Aucun transcodage implicite n'existe. Les conversions directes retournent la destination attendue. Lorsqu'une validation runtime peut échouer, la callable peut déclarer `faults UnicodeEncodingFault` au lieu de forcer un `ResultError` ou une variante `try...` parallèle. Exemples : ```text char::toUtf8Char() -> Utf8Char Utf8Char::toChar() -> char Utf8Char::toUtf16Char() -> Utf16Char Utf8Char::from(uint8) -> Utf8Char faults UnicodeEncodingFault Utf16Char::from(uint16) -> Utf16Char faults UnicodeEncodingFault Utf32Char::from(uint32) -> Utf32Char faults UnicodeEncodingFault Utf8Char::toUint8() -> uint8 faults UnicodeEncodingFault Utf16Char::toUint16() -> uint16 faults UnicodeEncodingFault Utf32Char::toUint32() -> uint32 ``` `UnicodeEncodingFault extends Fault` est le nom de travail du fault Core associé aux données encodées invalides ou aux réductions impossibles. Le Core n'expose pas simultanément `from(...)` et `tryFrom(...)` lorsque les deux opérations auraient exactement la même sémantique et ne différeraient que par le canal d'échec. La matrice normative détaillée est définie dans `annexes/B-unicode-encoding-conversions.md`. ## 21.5 Aucun mélange implicite de types — V1 REQUIS — FIGÉ Une API textuelle n'effectue jamais un transcodage implicite de son argument. ```text Utf8String text = ...; Utf16Char value = ...; text::append(value); // ERROR text::append(value::toUtf8Char()); // OK ``` Même règle pour concaténation, insertion, remplacement, recherche typée et construction. Les conversions sont effectuées explicitement avant l'opération métier. ## 21.6 Indexation — V1 REQUIS — FIGÉ `String` n'implémente pas `OpIndex`. ```text String text = ...; text[5]; // ERROR ``` Son unité logique est explicitement nommée : ```text text::scalarAt(index) -> char text::scalarCount() -> uint64 ``` Les strings encodées peuvent exposer `[]` en lecture pour leurs code units physiques : ```text Utf8String[index] -> uint8 Utf16String[index] -> uint16 Utf32String[index] -> uint32 ``` Elles n'exposent pas `OpIndexMut`, afin qu'une écriture brute ne puisse pas casser l'invariant d'encodage. ## 21.7 Accès scalar et caractère encodé — V1 REQUIS — FIGÉ EN PRINCIPE Pour un `UtfXString` : ```text encodedCharAt(scalarIndex) retourne le UtfXChar correspondant au scalar ordinal demandé scalarAt(scalarIndex) retourne le char correspondant ``` Exemples : ```text Utf8String::encodedCharAt(uint64) -> Utf8Char Utf16String::encodedCharAt(uint64) -> Utf16Char Utf32String::encodedCharAt(uint64) -> Utf32Char Utf8String::scalarAt(uint64) -> char Utf16String::scalarAt(uint64) -> char Utf32String::scalarAt(uint64) -> char ``` Un index de code unit et un ordinal de scalar sont des concepts distincts. Une API de décodage depuis un offset de code unit peut exister explicitement. En UTF-8/UTF-16, elle est faillible lorsqu'un offset peut pointer au milieu d'une séquence encodée. Le nom exact de cette API reste à stabiliser avec les vues/slices. ## 21.8 Comptage — V1 REQUIS — FIGÉ `String` expose : ```text scalarCount() ``` Les strings encodées distinguent : ```text codeUnitCount() scalarCount() ``` Ces deux propriétés restent distinctes même lorsqu'elles coïncident systématiquement dans UTF-32, car elles décrivent deux unités sémantiques différentes. ## 21.9 Itération — V1 REQUIS — FIGÉ EN PRINCIPE `String` possède une unité sémantique non ambiguë : ```text String implements Iterable ``` Pour `Utf8String`, `Utf16String` et `Utf32String`, plusieurs parcours utiles existent : ```text code units encoded chars Unicode scalars ``` Aucun `Iterable` direct unique n'est imposé aux strings encodées en V1. Les parcours sont explicites : ```text codeUnits() encodedChars() scalars() ``` Le type concret de vue/itérateur retourné sera fixé avec les collections et slices. ## 21.10 Mutation contrôlée — V1 REQUIS — FIGÉ `String` et `UtfXString` ne sont pas intrinsèquement immutables. Ils peuvent exposer des méthodes mutantes contrôlées. ```text String text = "abc"; text::append("def"); ``` Après l'appel, `text` contient la valeur modifiée selon le contrat de `append`. Pour les strings encodées, toute méthode mutante doit préserver l'invariant d'encodage. ```text Utf8String text = ...; Utf8Char value = ...; text::append(value); // OK ``` Une mutation brute de code unit reste interdite : ```text text[index] = 0xFF; // ERROR ``` Un accès `const` désactive les opérations mutantes via cet accès, sans rendre globalement immutable l'objet partagé. ## 21.11 Comparaison et normalisation — V1 REQUIS — FIGÉ EN PRINCIPE Aucune normalisation Unicode, case folding ou collation linguistique n'est implicite. Deux `String` sont égales selon leur séquence sémantique exacte de Unicode scalars. Des textes visuellement équivalents mais composés de séquences différentes peuvent donc être différents. Les normalisations NFC/NFD, case folding, grapheme segmentation et collations localisées relèvent d'API explicites Core/SDK à détailler. ## 21.12 Familles de littéraux texte — V1 REQUIS / RÉSERVÉ Les familles suivantes sont reconnues ou réservées parce qu'elles représentent des sémantiques distinctes : ```text "..." String normale, escapes actifs """...""" String normale multiligne r"..." String brute r"""...""" String brute multiligne i"..." String interpolée i"""...""" String interpolée multiligne ir"..." interpolation + contenu brut, réservé b"..." bytes, réservé br"..." bytes bruts, réservé u8"..." texte encodé UTF-8 explicitement, réservé u16"..." texte encodé UTF-16 explicitement, réservé u32"..." texte encodé UTF-32 explicitement, réservé c"..." chaîne compatible C, réservé cr"..." chaîne C brute, réservé t"..." template structuré, réservé ``` V1 doit au minimum couvrir les formes normales, multilignes, raw et interpolées. Le délimiteur interne de l'interpolation reste à finaliser entre les formes déjà inventoriées. ## 21.13 Chaînes multilignes — V1 REQUIS — FIGÉ Les triples quotes fournissent la forme multiligne. Le délimiteur de fermeture détermine l'indentation structurelle à retirer de chaque ligne. Une indentation supplémentaire volontaire dans le contenu est conservée. Lorsque le délimiteur d'ouverture multiligne est immédiatement suivi d'un retour à la ligne, ce premier retour structurel n'appartient pas à la valeur. Lorsque le délimiteur de fermeture se trouve seul après l'indentation structurelle d'une nouvelle ligne, le dernier retour structurel est également supprimé. Le formatter peut réindenter la structure source uniquement en préservant exactement la valeur sémantique du littéral. ## 21.14 Raw strings et escapes — V1 REQUIS — FIGÉ Les raw strings utilisent `r` contigu et peuvent employer zéro ou plusieurs `#` dans leur délimiteur. Aucun escape n'est interprété dans le contenu raw. Dans les `String` normales et les `char`, l'ensemble canonique reste : ```text \\ \" \' \n \r \t \0 \u{...} ``` `\u{...}` contient de 1 à 6 chiffres hexadécimaux, n'accepte pas `_`, doit être inférieur ou égal à `0x10FFFF` et ne peut pas désigner la plage surrogate UTF-16. `\xNN` reste réservé aux littéraux orientés octets. ## 21.15 Source Unicode et représentation — V1 REQUIS — FIGÉ EN PRINCIPE Le fichier source UTF-8 peut contenir directement des scalars Unicode valides dans `String`, `char`, commentaires et Saseldoc. Une séquence UTF-8 invalide est une erreur de source. La représentation physique interne de `String` reste indépendante de cette syntaxe source et peut varier suivant backend/target. ## 21.16 Sous-chaînes et représentation interne — V1 REQUIS — FIGÉ EN PRINCIPE La représentation interne de `String` n'est pas observable. Une implémentation peut notamment employer un stockage contigu, partagé, segmenté, copy-on-write, rope, small-string optimization ou une combinaison de ces techniques. `substring(...)` retourne une vraie `String` sémantiquement indépendante. ```text String a = "abcdef"; String b = a::substring(1..<4); ``` `b` représente indépendamment `"bcd"`. Une mutation ultérieure de `a` ne peut pas modifier la valeur observable de `b`, et inversement. Cette indépendance sémantique n'impose aucune copie physique immédiate : le runtime peut partager des segments/backing storage tant que le contrat reste respecté. Aucun type `StringView` n'est introduit ni réservé à ce stade. Il ne sera étudié que si un besoin concret apparaît. ---