package chat // Code generated by the Holanet PDL compiler. DO NOT EDIT. // The source file is located at // Please edit that file instead, and re-compile it to this location. // HOPP, TAPE, METADAPT, PDL/0 (c) 2025 holanet.xyz import "fmt" import "git.tebibyte.media/sashakoshka/hopp" import "git.tebibyte.media/sashakoshka/hopp/tape" // Table is a KTV table with an undefined schema. type Table = map[uint16] any // Message is any message that can be sent along this protocol. type Message interface { tape.Encodable tape.Decodable // Method returns the method code of the message. Method() uint16 } // Send encodes a message and sends it along a transaction. func Send(trans hopp.Trans, message Message) (n int, err error) { writer, err := trans.SendWriter(message.Method()) if err != nil { return n, err } defer writer.Close() encoder := tape.NewEncoder(writer) n, err = message.Encode(encoder) if err != nil { return n, err } return n, encoder.Flush() } // canAssign determines if data from the given source tag can be assigned to // a Go type represented by destination. It is designed to receive destination // values from [generate.Generator.generateCanAssign]. The eventual Go type and // the destination tag must come from the same (or hash-equivalent) PDL type. func canAssign(destination, source tape.Tag) bool { if destination.Is(source) { return true } if (destination.Is(tape.SBA) || destination.Is(tape.LBA)) && (source.Is(tape.SBA) || source.Is(tape.LBA)) { return true } return false } // boolInt converts a bool to an integer. func boolInt(input bool) int { if input { return 1 } else { return 0 } } // ensure ucontainer is always imported var _ hopp.Option[int] // Error is sent by a party when the other party has done something erroneous. The // valid error codes are: // // - 0: General, unspecified error // // The description field, if specified, determines a human-readable error to be // shown to the user. The sending party must immediately close the transaction // after this message is sent. type MessageError struct { Code uint16 Description hopp.Option[string] } // Method returns the message's method number. func(this *MessageError) Method() uint16 { return 0x0000 } // Encode encodes this message's tag and value. func(this *MessageError) Encode(encoder *tape.Encoder) (n int, err error) { tag_1 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_1) n += nn; if err != nil { return n, err } if 2 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(2, tag_1.CN() + 1) n += nn; if err != nil { return n, err } { if value, ok := (*this).Description.Value(); ok { nn, err = encoder.WriteUint16(0x0001) n += nn; if err != nil { return n, err } tag_2 := tape.StringTag(string(value)) nn, err = encoder.WriteUint8(uint8(tag_2)) n += nn; if err != nil { return n, err } if len(value) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_2.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len(value)), tag_2.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte(value)) n += nn; if err != nil { return n, err } } nn, err = encoder.WriteUint16(0x0000) n += nn; if err != nil { return n, err } tag_3 := tape.LI.WithCN(1) nn, err = encoder.WriteUint8(uint8(tag_3)) n += nn; if err != nil { return n, err } nn, err = encoder.WriteUint16(uint16((*this).Code)) n += nn; if err != nil { return n, err } } return n, nil } // Decode decodes this message's tag and value. func(this *MessageError) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_1d505103df99c95e6bed0800d0ea881a_MessageError(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } // Success is sent by a party when it has successfully completed a task given to it // by the other party. The sending party must immediately close the transaction // after this message is sent. type MessageSuccess struct { } // Method returns the message's method number. func(this *MessageSuccess) Method() uint16 { return 0x0001 } // Encode encodes this message's tag and value. func(this *MessageSuccess) Encode(encoder *tape.Encoder) (n int, err error) { tag_4 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_4) n += nn; if err != nil { return n, err } if 0 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(0, tag_4.CN() + 1) n += nn; if err != nil { return n, err } { } return n, nil } // Decode decodes this message's tag and value. func(this *MessageSuccess) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_99914b932bd37a50b983c5e7c90ae93b_MessageSuccess(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } // Join is sent by the client when it wishes to join a room. It must begin a new // transaction, and that transaction will persist while the user is in that room. // Messages having to do with the room will be sent along this transaction. To // leave the room, the client must close the transaction. type MessageJoin struct { Room string Nickname string } // Method returns the message's method number. func(this *MessageJoin) Method() uint16 { return 0x0200 } // Encode encodes this message's tag and value. func(this *MessageJoin) Encode(encoder *tape.Encoder) (n int, err error) { tag_5 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_5) n += nn; if err != nil { return n, err } if 2 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(2, tag_5.CN() + 1) n += nn; if err != nil { return n, err } { nn, err = encoder.WriteUint16(0x0000) n += nn; if err != nil { return n, err } tag_6 := tape.StringTag(string((*this).Room)) nn, err = encoder.WriteUint8(uint8(tag_6)) n += nn; if err != nil { return n, err } if len((*this).Room) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_6.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Room)), tag_6.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Room)) n += nn; if err != nil { return n, err } nn, err = encoder.WriteUint16(0x0001) n += nn; if err != nil { return n, err } tag_7 := tape.StringTag(string((*this).Nickname)) nn, err = encoder.WriteUint8(uint8(tag_7)) n += nn; if err != nil { return n, err } if len((*this).Nickname) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_7.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Nickname)), tag_7.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Nickname)) n += nn; if err != nil { return n, err } } return n, nil } // Decode decodes this message's tag and value. func(this *MessageJoin) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_2c5f22d9503118676b4c5584211a4a95_MessageJoin(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } // Chat is sent by the client when it wishes to post a message to the room. It is // also relayed by the server to other clients to notify them of the message. It // must be sent within a room transaction. type MessageChat struct { Content string Nickname string } // Method returns the message's method number. func(this *MessageChat) Method() uint16 { return 0x0300 } // Encode encodes this message's tag and value. func(this *MessageChat) Encode(encoder *tape.Encoder) (n int, err error) { tag_8 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_8) n += nn; if err != nil { return n, err } if 2 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(2, tag_8.CN() + 1) n += nn; if err != nil { return n, err } { nn, err = encoder.WriteUint16(0x0000) n += nn; if err != nil { return n, err } tag_9 := tape.StringTag(string((*this).Content)) nn, err = encoder.WriteUint8(uint8(tag_9)) n += nn; if err != nil { return n, err } if len((*this).Content) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_9.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Content)), tag_9.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Content)) n += nn; if err != nil { return n, err } nn, err = encoder.WriteUint16(0x0001) n += nn; if err != nil { return n, err } tag_10 := tape.StringTag(string((*this).Nickname)) nn, err = encoder.WriteUint8(uint8(tag_10)) n += nn; if err != nil { return n, err } if len((*this).Nickname) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_10.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Nickname)), tag_10.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Nickname)) n += nn; if err != nil { return n, err } } return n, nil } // Decode decodes this message's tag and value. func(this *MessageChat) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_5c1cf9347bb6d9f41cee64b186392d24_MessageChat(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } // JoinNotify is sent by the server when another client joins the room. It must be // sent within a room transaction. type MessageJoinNotify struct { Nickname string } // Method returns the message's method number. func(this *MessageJoinNotify) Method() uint16 { return 0x0400 } // Encode encodes this message's tag and value. func(this *MessageJoinNotify) Encode(encoder *tape.Encoder) (n int, err error) { tag_11 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_11) n += nn; if err != nil { return n, err } if 1 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(1, tag_11.CN() + 1) n += nn; if err != nil { return n, err } { nn, err = encoder.WriteUint16(0x0000) n += nn; if err != nil { return n, err } tag_12 := tape.StringTag(string((*this).Nickname)) nn, err = encoder.WriteUint8(uint8(tag_12)) n += nn; if err != nil { return n, err } if len((*this).Nickname) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_12.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Nickname)), tag_12.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Nickname)) n += nn; if err != nil { return n, err } } return n, nil } // Decode decodes this message's tag and value. func(this *MessageJoinNotify) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_68c536511e6d598462efc482144438e9_MessageJoinNotify(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } // LeaveNotify is sent by the server when another client leaves the room. It must // be sent within a room transaction. type MessageLeaveNotify struct { Nickname string } // Method returns the message's method number. func(this *MessageLeaveNotify) Method() uint16 { return 0x0401 } // Encode encodes this message's tag and value. func(this *MessageLeaveNotify) Encode(encoder *tape.Encoder) (n int, err error) { tag_13 := tape.KTV.WithCN(0) nn, err := encoder.WriteTag(tag_13) n += nn; if err != nil { return n, err } if 1 > tape.MaxStructureLength { return n, tape.ErrTooLong } nn, err = encoder.WriteUintN(1, tag_13.CN() + 1) n += nn; if err != nil { return n, err } { nn, err = encoder.WriteUint16(0x0000) n += nn; if err != nil { return n, err } tag_14 := tape.StringTag(string((*this).Nickname)) nn, err = encoder.WriteUint8(uint8(tag_14)) n += nn; if err != nil { return n, err } if len((*this).Nickname) > tape.MaxStructureLength { return n, tape.ErrTooLong } if tag_14.Is(tape.LBA) { nn, err = encoder.WriteUintN(uint64(len((*this).Nickname)), tag_14.CN()) n += nn; if err != nil { return n, err } } nn, err = encoder.Write([]byte((*this).Nickname)) n += nn; if err != nil { return n, err } } return n, nil } // Decode decodes this message's tag and value. func(this *MessageLeaveNotify) Decode(decoder *tape.Decoder) (n int, err error) { tag, nn, err := decoder.ReadTag() n += nn; if err != nil { return n, err } if !(canAssign(tape.KTV, tag)) { nn, err = tape.Skim(decoder, tag) n += nn; if err != nil { return n, err } return n, nil } nn, err = decodeBranch_68c536511e6d598462efc482144438e9_MessageLeaveNotify(this, decoder, tag) n += nn; if err != nil { return n, err } return n, nil } func decodeBranch_1d505103df99c95e6bed0800d0ea881a_MessageError(this *MessageError, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_15 uint64 if length_15 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_15, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_15 { var fieldKey_16 uint16 fieldKey_16, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_17 tape.Tag fieldTag_17, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_16 { case 0x0000: if !(canAssign(tape.LI, fieldTag_17)) { tape.Skim(decoder, fieldTag_17) continue } destination_18, nn, err := decoder.ReadUint16() n += nn; if err != nil { return n, err } *(&(this.Code)) = destination_18 case 0x0001: if !(canAssign(tape.LBA, fieldTag_17)) { tape.Skim(decoder, fieldTag_17) continue } var destination_19 string var length_20 uint64 if fieldTag_17.Is(tape.LBA) { length_20, nn, err = decoder.ReadUintN(int(fieldTag_17.CN())) n += nn; if err != nil { return n, err } } else { length_20 = uint64(fieldTag_17.CN()) } if length_20 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_20) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&destination_19) = string(buffer) this.Description = hopp.O(destination_19) default: tape.Skim(decoder, fieldTag_17) continue } } return n, nil } func decodeBranch_99914b932bd37a50b983c5e7c90ae93b_MessageSuccess(this *MessageSuccess, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_21 uint64 if length_21 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_21, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_21 { var fieldKey_22 uint16 fieldKey_22, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_23 tape.Tag fieldTag_23, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_22 { default: tape.Skim(decoder, fieldTag_23) continue } } return n, nil } func decodeBranch_2c5f22d9503118676b4c5584211a4a95_MessageJoin(this *MessageJoin, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_24 uint64 if length_24 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_24, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_24 { var fieldKey_25 uint16 fieldKey_25, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_26 tape.Tag fieldTag_26, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_25 { case 0x0000: if !(canAssign(tape.LBA, fieldTag_26)) { tape.Skim(decoder, fieldTag_26) continue } var length_27 uint64 if fieldTag_26.Is(tape.LBA) { length_27, nn, err = decoder.ReadUintN(int(fieldTag_26.CN())) n += nn; if err != nil { return n, err } } else { length_27 = uint64(fieldTag_26.CN()) } if length_27 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_27) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Room)) = string(buffer) case 0x0001: if !(canAssign(tape.LBA, fieldTag_26)) { tape.Skim(decoder, fieldTag_26) continue } var length_28 uint64 if fieldTag_26.Is(tape.LBA) { length_28, nn, err = decoder.ReadUintN(int(fieldTag_26.CN())) n += nn; if err != nil { return n, err } } else { length_28 = uint64(fieldTag_26.CN()) } if length_28 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_28) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Nickname)) = string(buffer) default: tape.Skim(decoder, fieldTag_26) continue } } return n, nil } func decodeBranch_5c1cf9347bb6d9f41cee64b186392d24_MessageChat(this *MessageChat, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_29 uint64 if length_29 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_29, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_29 { var fieldKey_30 uint16 fieldKey_30, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_31 tape.Tag fieldTag_31, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_30 { case 0x0000: if !(canAssign(tape.LBA, fieldTag_31)) { tape.Skim(decoder, fieldTag_31) continue } var length_32 uint64 if fieldTag_31.Is(tape.LBA) { length_32, nn, err = decoder.ReadUintN(int(fieldTag_31.CN())) n += nn; if err != nil { return n, err } } else { length_32 = uint64(fieldTag_31.CN()) } if length_32 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_32) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Content)) = string(buffer) case 0x0001: if !(canAssign(tape.LBA, fieldTag_31)) { tape.Skim(decoder, fieldTag_31) continue } var length_33 uint64 if fieldTag_31.Is(tape.LBA) { length_33, nn, err = decoder.ReadUintN(int(fieldTag_31.CN())) n += nn; if err != nil { return n, err } } else { length_33 = uint64(fieldTag_31.CN()) } if length_33 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_33) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Nickname)) = string(buffer) default: tape.Skim(decoder, fieldTag_31) continue } } return n, nil } func decodeBranch_68c536511e6d598462efc482144438e9_MessageJoinNotify(this *MessageJoinNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_34 uint64 if length_34 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_34, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_34 { var fieldKey_35 uint16 fieldKey_35, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_36 tape.Tag fieldTag_36, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_35 { case 0x0000: if !(canAssign(tape.LBA, fieldTag_36)) { tape.Skim(decoder, fieldTag_36) continue } var length_37 uint64 if fieldTag_36.Is(tape.LBA) { length_37, nn, err = decoder.ReadUintN(int(fieldTag_36.CN())) n += nn; if err != nil { return n, err } } else { length_37 = uint64(fieldTag_36.CN()) } if length_37 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_37) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Nickname)) = string(buffer) default: tape.Skim(decoder, fieldTag_36) continue } } return n, nil } func decodeBranch_68c536511e6d598462efc482144438e9_MessageLeaveNotify(this *MessageLeaveNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) { var nn int var length_38 uint64 if length_38 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } length_38, nn, err = decoder.ReadUintN(int(tag.CN()) + 1) n += nn; if err != nil { return n, err } for _ = range length_38 { var fieldKey_39 uint16 fieldKey_39, nn, err = decoder.ReadUint16() n += nn; if err != nil { return n, err } var fieldTag_40 tape.Tag fieldTag_40, nn, err = decoder.ReadTag() n += nn; if err != nil { return n, err } switch fieldKey_39 { case 0x0000: if !(canAssign(tape.LBA, fieldTag_40)) { tape.Skim(decoder, fieldTag_40) continue } var length_41 uint64 if fieldTag_40.Is(tape.LBA) { length_41, nn, err = decoder.ReadUintN(int(fieldTag_40.CN())) n += nn; if err != nil { return n, err } } else { length_41 = uint64(fieldTag_40.CN()) } if length_41 > uint64(tape.MaxStructureLength) { return n, tape.ErrTooLong } buffer := make([]byte, length_41) nn, err = decoder.Read(buffer) n += nn; if err != nil { return n, err } *(&(this.Nickname)) = string(buffer) default: tape.Skim(decoder, fieldTag_40) continue } } return n, nil } // Receive decodes a message from a transaction and returns it as a value. // Use a type switch to determine what type of message it is. func Receive(trans hopp.Trans) (message any, n int, err error) { method, reader, err := trans.ReceiveReader() decoder := tape.NewDecoder(reader) if err != nil { return nil, n, err } switch method { case 0x0401: var message MessageLeaveNotify nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil case 0x0000: var message MessageError nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil case 0x0001: var message MessageSuccess nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil case 0x0200: var message MessageJoin nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil case 0x0300: var message MessageChat nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil case 0x0400: var message MessageJoinNotify nn, err := message.Decode(decoder) n += nn; if err != nil { return nil, n, err } return message, n, nil } return nil, n, fmt.Errorf("%w: M%04X", hopp.ErrUnknownMethod, method) }