【WIP】apple/swift - stdlib/public/core/Codable.swift.gyb コードリーディング

概要

https://github.com/apple/swift/blob/master/stdlib/public/core/Codable.swift.gyb

gyb : codable_types

gybによる定義で書かれていて、primitiveな型のみに絞って自動生成される? TBD

codable_types = ['Bool', 'String', 'Double', 'Float',
                 'Int', 'Int8', 'Int16', 'Int32', 'Int64',
                 'UInt', 'UInt8', 'UInt16', 'UInt32', 'UInt64']

CodingKey

エンコーディングとデコーディングのキーとして使用できる型とある

文字列と数値によって定義が分かれていて、

文字列

var stringValue: String { get }
init?(stringValue: String)

数値

var intValue: Int? { get }
init?(intValue: Int)

このようになっていて文字列がkeyは分かりやすいが、数値がkeyのパターンでの用途は珍しいように感じる

CodingKeyを使う場面としてはCodableプロトコルに準拠しつつエンコードorデコード時にkey名が違うような場面で必要になる

まだこの定義だけだとその辺りの組み替えは見受けられないので利用側の定義を見ていきたい

Codable

外部表現の出入りを変えることができる型定義

public typealias Codable = Encodable & Decodable

CodingUserInfoKey

エンコード・デコード時に用いられるユーザー定義key

RawRepresentableプロトコルに準拠しており、associated typeとしてRawValueにStringを指定しそのままkeyとなる

_DictionaryCodingKey

@usableFromInline // FIXME(sil-serialize-all)
@_fixed_layout // FIXME(sil-serialize-all)
internal struct _DictionaryCodingKey : CodingKey

Dictionaryのextensionとしてconditional conformanceな以下の定義で利用されている内部コンテナのinternalなkey定義

extension Dictionary : Encodable where Key : Encodable, Value : Encodable
extension Dictionary : Decodable where Key : Decodable, Value : Decodable

CodingKeyプロトコルを親としている

このようにDictionaryをEncodable&Decodableに準拠させることでCodableな要素のみを含んだ場合にCodableの枠組みとして扱えるになっている

_GenericIndexKey

@usableFromInline // FIXME(sil-serialize-all)
@_fixed_layout // FIXME(sil-serialize-all)
internal struct _GenericIndexKey : CodingKey

DecodingErrorで使われているcontainerのindexからkeyとして扱うのに用いられているinternalなkey定義

intValueとstringValueからkeyの値を取る方式のCodingKeyプロトコルのintValueのみをkeyとして扱うように制限を加えられている模様

エンコード

Encodable

外部の表現に自身をエンコードすることができる型

encode

Encodableに定義されている唯一の関数

func encode(to encoder: Encoder) throws

この値を指定されたEncoderにエンコードする

TBD

Encoder

TBD

codingPath

var codingPath: [CodingKey] { get }

エンコード時にこのポイントに到達するために使用されるCodingKeyのパス

userInfo

var userInfo: [CodingUserInfoKey : Any] { get }

エンコーディングのためにユーザーによって設定されたコンテキスト情報

container

func container<Key>(keyedBy type: Key.Type) throws -> KeyedEncodingContainer<Key>

unkeyedContainer

func unkeyedContainer() throws -> UnkeyedEncodingContainer

TBD

singleValueContainer

func singleValueContainer() throws -> SingleValueDecodingContainer

TBD

KeyedEncodingContainerProtocol

TBD

KeyedEncodingContainer<K : CodingKey>

TBD

UnkeyedEncodingContainer

TBD

SingleValueEncodingContainer

TBD

EncodingError

TBD

_KeyedEncodingContainerBase<Key : CodingKey>

TBD

_KeyedEncodingContainerBox<Concrete : KeyedEncodingContainerProtocol>

TBD

デコード

Decodable

外部の表現から自身をデコードすることができる型

decode

Decodableに定義されている唯一の関数

init(from decoder: Decoder) throws

TBD

Decoder

TBD

KeyedDecodingContainerProtocol

TBD

KeyedDecodingContainer<K : CodingKey>

TBD

UnkeyedDecodingContainer

TBD

SingleValueDecodingContainer

TBD

DecodingError

TBD

_KeyedDecodingContainerBase<Key : CodingKey>

TBD

_KeyedDecodingContainerBox<Concrete : KeyedDecodingContainerProtocol>

TBD