diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..70d8a9b --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +> +> ॐ भूर्भुवः स्वः +> +> तत्स॑वि॒तुर्वरे॑ण्यं॒ +> +> भर्गो॑ दे॒वस्य॑ धीमहि। +> +> धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +> + +# बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। + +> एक सरल संचार सहायक और संलग्न तंत्र। +> + +***एक रचनात्मक भारतीय उत्पाद।*** + +## `tppi` stands for Tilde Pipe Plus Interface + +> A simple communication helper and enclosing mechanism called **TPPI protocol**. + +There are two parts to this protocol: + +- *Organization* - Build the compatible data representation called **TPPI content**. +- *Encapsulation* - Prepare a compatible packet with necessary safeguards called **TPPI packet**. + +This is **string oriented protocol** with *special safeguards* for **TPPI protocol.** + +The following symbols are considered special to **TPPI protocol**: + +- `~` Tilde Symbol +- `|` Pipe Symbol +- `+` Plus Symbol + +These *symbol are replaced* by the following as *safeguards* for **TPPI packet**: + +- `|` converts to `\\x7C` +- `+` converts to `\\x2B` + +These *symbols are replaced* for *safeguards* in data specified for **TPPI contents** : + + `~` converts to `%7E` + `|` converts to `%7C` + `+` converts to `%2B` + +The **TPPI protocol** contains special annotations: + +- `~|` is used to indicate the **start** of the **TPPI Packet** +- `|~` is used to indicate the **end** of the **TPPI Packet** +- `|` is used to separate the **TPPI contents** in a **TPPI Packet** +- `~` are used to organize the **TPPI contents** with Type, tags, & data. +- `~||~` indicates a **TPPI packet** *without any contents* +- `+` is used to join TPPI packets together. + +Collection rule for TPPI packets: + +- If **TPPI packet** are sent one at a time then no special addition is needed. +- In case *collection* of **TPPI packets** need to be sent then `+` symbol is used. + +Rules for **TPPI content**: + +- The *content mist be filtered* with necessary *safeguards*. +- **Type Signature**: Each **TPPI content** must have a **Type Signature** that tells what type of data it contains and helps in *Discovery process* later. In case no **Type Signature** is provided `UN` would be used to indicate `unknown` Type`. + **Type Signature** can't be left blank and recommended to be added. +- **Tag**: Each **TPPI content** can have a string name or tag that can help better identify the data enclosed. This would later be used for *Discovery process*. This is an *Optional field* and can be omitted in the **TPPI content**. +- **Data**: The **TPPI content** encloses the data provided in *string form*, that can later be retrieved using the *Discovery process*. +- The fields **Type Signature**, *(optional)* **Tag** and **Data** are separated by `~` Symbol in a **TPPI content**. + +**TPPI Content Processes**: + +- **Specify**: In this process the **Type Signature**, *(optional)* **Tag** and **Data** are joined together in **TPPI Content** form. This follows the rules for **TPPI content**. This typically happens before preparing the **TPPI packet**. +- **Discover**: In this process the **Type Signature**, *(optional)* **Tag** and **Data** are recovered from the supplied **TPPI Content**. This follows the same rules for **TPPI content** in order to find the enclosed data. This is typically done after receiving the TPPI packet and getting the **TPPI contents**. + +**TPPI Packet Processes**: + +- **Assemble**: In this process the **TPPI contents** are *filtered* and *joined together* into a **TPPI packet** following respective rules. This however *should not be used* for Joining *multiple TPPI packets*. +- **Disassemble**: In this process the incoming **TPPI packet** is broken into into multiple **TPPI contents** with *filtering/safeguards* removed. This however *should not be used* directly on the *Incoming TPPI packet* as *it would not be able to split apart TPPI packets*. +- **Join**: This is the process of *Joining multiple packets* before sending over the **combined TPPI packets**. +- **Split**: This is process perform as soon as the **TPPI packets** are received. *Only after this the process* of *Disassembly can begin*. + +*Background behind the name:* + +> The name `tppi` has been taken from a story of an imaginative kid +> discovering the mysteries of the Universe and the world all around +> from a remote village in the heart of Karnataka, Bharat(India). +> + +## कार्यविधि - Usage + +Include into a project: + +```sh +go get github.com/boseji/go-tppi@latest +``` + +Usage in Program: + +```go +package main + +import ( + "fmt" + "github.com/boseji/go-tppi" +) + +func main() { + fmt.Println(tppi.Assemble("Hari Aum")) + + // Output: + // ~|Hari Aum|~ +} +``` + +## License + +`SPDX: Apache-2.0` + +`tppi` stands for Tilde Pipe Plus Interface + +Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/archived-old-code.tar b/archived-old-code.tar new file mode 100644 index 0000000..d6b7e99 Binary files /dev/null and b/archived-old-code.tar differ diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..ab8bd88 --- /dev/null +++ b/doc.go @@ -0,0 +1,146 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================= +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// tppi stands for Tilde Pipe Plus Interface, +// A simple communication helper and enclosing mechanism called TPPI protocol. +// +// There are two parts to this protocol: +// +// Organization - Build the compatible data representation called **TPPI content**. +// Encapsulation - Prepare a compatible packet with necessary safeguards called **TPPI packet**. +// +// This is string oriented protocol with special safeguards for TPPI protocol. +// +// The following symbols are considered special to TPPI protocol: +// +// `~` Tilde Symbol +// `|` Pipe Symbol +// `+` Plus Symbol +// +// These symbol are replaced by the following as safeguards for TPPI packet: +// +// `|` converts to `\\x7C` +// `+` converts to `\\x2B` +// +// These symbols are replaced for safeguards in data specified for +// TPPI contents : +// +// `~` converts to `%7E` +// `|` converts to `%7C` +// `+` converts to `%2B` +// +// The TPPI protocol contains special annotations: +// +// `~|` is used to indicate the **start** of the TPPI Packet +// `|~` is used to indicate the **end** of the TPPI Packet +// `|` is used to separate the TPPI contents in a TPPI Packet +// `~` are used to organize the TPPI contents with Type, tags, & data. +// `~||~` indicates a TPPI packet without any contents +// `+` is used to join TPPI packets together. +// +// Collection rule for TPPI packets: +// +// If TPPI packet are sent one at a time then no special addition is needed. +// In case collection of TPPI packets need to be sent then `+` symbol is used. +// +// Rules for TPPI content: +// +// The content mist be filtered with necessary safeguards. +// Type Signature : Each TPPI content must have a Type Signature that tells +// what type of data it contains and helps in Discovery process later. +// In case no Type Signature is provided `UN` would be used to indicate +// `unknown` Type`. +// Type Signature can't be left blank and recommended to be added. +// Tag : Each TPPI content can have a string name or tag that can help better +// identify the data enclosed. This would later be used for Discovery +// process. This is an Optional field and can be omitted in the +// TPPI content. +// Data: The TPPI content encloses the data provided in string form, that +// can later be retrieved using the Discovery process. +// The fields Type Signature, (optional) Tag and Data are separated +// by `~` Symbol in a TPPI content. +// +// TPPI Content Processes: +// +// Specify : In this process the Type Signature, (optional) Tag and Data are +// joined together in TPPI Content form. This follows the rules +// for TPPI content. This typically happens before preparing the +// TPPI packet. +// Discover : In this process the Type Signature, (optional) Tag and Data are +// recovered from the supplied TPPI Content. This follows the same rules +// for TPPI content in order to find the enclosed data. This is typically +// done after receiving the TPPI packet and getting the TPPI contents. +// +// TPPI Packet Processes: +// +// Assemble : In this process the TPPI contents are filtered and joined +// together into a TPPI packet following respective rules. +// This however should not be used for Joining multiple TPPI packets. +// Disassemble : In this process the incoming TPPI packet is broken into +// into multiple TPPI contents with filtering removed. +// This however should not be used directly on the Incoming TPPI packet +// as it would not be able to split apart TPPI packets. +// Join : This is the process of Joining multiple packets before sending over +// the combined TPPI packets. +// Split : This is process perform as soon as the TPPI packets are received. +// Only after this the process of Disassembly can begin. +// +// Background behind the name: +// +// The name `tppi` has been taken from a story of an imaginative kid +// discovering the mysteries of the Universe and the world all around +// from a remote village in the heart of Karnataka, Bharat(India). +package tppi diff --git a/example_Discover_test.go b/example_Discover_test.go new file mode 100644 index 0000000..7d5b152 --- /dev/null +++ b/example_Discover_test.go @@ -0,0 +1,105 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi_test + +import ( + "fmt" + "strings" + + "guthub.com/boseji/go-tppi" +) + +func (b *myBool) Recover(Type, Tag, Data string) error { + if Type != myBoolTypeSignature { + return fmt.Errorf("invalid bool type") + } + b.Tag = Tag + if Data == myBoolDataTrue { + b.bool = true + } else if Data == myBoolDataFalse { + b.bool = false + } else { + return fmt.Errorf("invalid bool data") + } + return nil +} + +func (m *myStruct) Recover(Type, Tag, Data string) (err error) { + if Type != myStructTypeSig { + return fmt.Errorf("wrong type supplied") + } + _ = Tag + sa := strings.Split(Data, " ") + if len(sa) != 3 { + return fmt.Errorf("malformed data") + } + + _, err = fmt.Sscanf(Data, myStructFormat, &m.TimeStamp, &m.Value, &m.Topic) + return +} + +func ExampleDiscover() { + b := myBool{} + srcBool := "B~bit%7E5~1" + err := tppi.Discover(srcBool, b.Recover) + if err != nil { + fmt.Printf("failed to Discover - %v\n", err) + return + } + fmt.Printf("%q Transforms back %#v\n", srcBool, b) + + m := myStruct{} + srcStruct := "MSTR~myStruct~134000000 12.345000 \"sensor/12\"" + err = tppi.Discover(srcStruct, m.Recover) + if err != nil { + fmt.Printf("failed to Discover - %v\n", err) + return + } + fmt.Printf("%q Transforms back\n", srcStruct) + fmt.Printf("%#v", m) + + // Output: + // "B~bit%7E5~1" Transforms back tppi_test.myBool{bool:true, Tag:"bit~5"} + // "MSTR~myStruct~134000000 12.345000 \"sensor/12\"" Transforms back + // tppi_test.myStruct{TimeStamp:134000000, Value:12.345, Topic:"sensor/12"} +} diff --git a/example_Protocol_test.go b/example_Protocol_test.go new file mode 100644 index 0000000..6727349 --- /dev/null +++ b/example_Protocol_test.go @@ -0,0 +1,132 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi_test + +import ( + "fmt" + + "guthub.com/boseji/go-tppi" +) + +func ExampleAssemble() { + ba := []myBool{ + {true, "Bit~0"}, + {false, "Bit-1"}, + {false, "Bit-2"}, + {true, "Bit-3"}, + } + sa := make([]string, 0, len(ba)) + for _, b := range ba { + sa = append(sa, tppi.Specify(b.Type(), b.Tag, b.String)) + } + s := tppi.Assemble(sa...) + s = tppi.PacketJoin(s) + fmt.Println(s) + + // Output: + // ~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~ +} + +func ExampleDisassemble() { + ba := make([]bool, 4) + ta := make([]string, 4) + srcBool := "~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~" + s := tppi.SplitPacket(srcBool) + if len(s) != 1 { + fmt.Println("expected it to 1 packet") + return + } + sa := tppi.Disassemble(s[0]) + if len(sa) != len(ba) { + fmt.Println("Packet does not contain enough data") + return + } + for i, s := range sa { + err := tppi.Discover(s, func(s1, s2, s3 string) error { + if s1 != "B" { + return fmt.Errorf("invalid type Signature") + } + ta[i] = s2 + switch s3 { + case "1": + ba[i] = true + case "0": + ba[i] = false + default: + return fmt.Errorf("invalid value") + } + return nil + }) + if err != nil { + fmt.Println("unable to discover -", err) + return + } + } + fmt.Println(ba) + fmt.Println(ta) + + // Output: + // [true false false true] + // [Bit~0 Bit-1 Bit-2 Bit-3] +} + +func ExamplePacketJoin() { + sa := []string{ + "~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~", + "~|S~Bit Wise Data|~", + } + s := tppi.PacketJoin(sa...) + fmt.Println(s) + + // Output: + // ~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~+~|S~Bit Wise Data|~ +} + +func ExampleSplitPacket() { + s := "~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~+~|S~Bit Wise Data|~" + sa := tppi.SplitPacket(s) + fmt.Println(sa) + + // Output: + // [~|B~Bit%7E0~1|B~Bit-1~0|B~Bit-2~0|B~Bit-3~1|~ ~|S~Bit Wise Data|~] +} diff --git a/example_Specify_test.go b/example_Specify_test.go new file mode 100644 index 0000000..f30f0f3 --- /dev/null +++ b/example_Specify_test.go @@ -0,0 +1,109 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi_test + +import ( + "fmt" + "time" + + "guthub.com/boseji/go-tppi" +) + +type myBool struct { + bool + Tag string +} + +const ( + myBoolTypeSignature = "B" + myBoolDataTrue = "1" + myBoolDataFalse = "0" +) + +func (b myBool) Type() string { + return myBoolTypeSignature +} + +func (b myBool) String() string { + if b.bool { + return myBoolDataTrue + } + return myBoolDataFalse +} + +type myStruct struct { + TimeStamp time.Duration + Value float32 + Topic string +} + +const ( + myStructTypeSig = "MSTR" + myStructFormat = "%d %f %q" +) + +func (m myStruct) Type() string { + return myStructTypeSig +} + +func (m myStruct) String() string { + return fmt.Sprintf(myStructFormat, m.TimeStamp, m.Value, m.Topic) +} + +func ExampleSpecify() { + b := myBool{true, "bit~5"} + s := tppi.Specify(b.Type(), b.Tag, b.String) + fmt.Printf("%#v transforms into %q\n", b, s) + + m := myStruct{134 * time.Millisecond, 12.345, "sensor/12"} + sa := tppi.Specify(m.Type(), "myStruct", m.String) + fmt.Printf("%#v\n", m) + fmt.Println("transforms into") + fmt.Println(sa) + + // Output: + // tppi_test.myBool{bool:true, Tag:"bit~5"} transforms into "B~bit%7E5~1" + // tppi_test.myStruct{TimeStamp:134000000, Value:12.345, Topic:"sensor/12"} + // transforms into + // MSTR~myStruct~134000000 12.345000 "sensor/12" +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b6f422d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module guthub.com/boseji/go-tppi + +go 1.22.6 diff --git a/org.go b/org.go new file mode 100644 index 0000000..5adbdaa --- /dev/null +++ b/org.go @@ -0,0 +1,129 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi + +import ( + "fmt" + "strings" +) + +// Specify helps to organize the data to create TPPI content. +// Here we need the Type Signature, an optional Tag and a function, that +// returns the string form of the Data to be enclosed in the TPPI content. +// The Type, Tag and Data is filtered with TPPI content safeguards before being +// processed into the TPPI content form. The data function has the signature +// `func() string`, this only gives one value considered as the string +// string representation of the data. +func Specify(typeSignature, tag string, fn func() string) string { + ta := make([]string, 0, 3) + if len(typeSignature) == 0 { + typeSignature = "UN" + } + ta = append(ta, typeSignature) + if len(tag) > 0 { + ta = append(ta, tag) + } + if fn != nil { + ta = append(ta, fn()) + } else { + return "" // We can't do much without this function + } + // Filter out the Data with TPPI content safeguards + sa := make([]string, 0, len(ta)) + for _, i := range ta { + i = strings.ReplaceAll(i, "|", "%7C") + i = strings.ReplaceAll(i, "+", "%2B") + i = strings.ReplaceAll(i, "~", "%7E") + sa = append(sa, i) + } + s := strings.Join(sa, "~") + return s +} + +// Discover helps to recover the data from the TPPI content. +// In order to begin the operation we need the TPPI content in string form. +// We also need a function that would be called with the discovered +// Type Signature, Tag and Data in string form. This function helps +// to recreate the data from the String form enclosed earlier in the +// TPPI content form. Here is the signature of the function +// `func(TypeSignature, Tag, Data string) error`. The function can also +// return an error indicating that the data or any of the parameters +// are invalid or damaged. The supplied Type Signature, Tag and Data are +// restored from the fileted TPPI content safeguards before calling the +// function. +func Discover(s string, fn func(string, string, string) error) (err error) { + if len(s) == 0 || fn == nil { + err = fmt.Errorf("wrong inputs for discover operation") + return + } + if strings.ContainsAny(s, "|+") { + err = fmt.Errorf("wrong data or damage can't discover") + return + } + // Split with Separator + sa := strings.Split(s, "~") + // Filter + if len(sa) > 1 { + for i, s := range sa { + s = strings.ReplaceAll(s, "%7C", "|") + s = strings.ReplaceAll(s, "%2B", "+") + s = strings.ReplaceAll(s, "%7E", "~") + sa[i] = s + } + } + // Check + switch len(sa) { + case 2: + err = fn(sa[0], "", sa[1]) + case 3: + err = fn(sa[0], sa[1], sa[2]) + default: + err = fmt.Errorf("invalid data discovered") + } + if err != nil { + err = fmt.Errorf("failed to discover due to process error - %v", + err) + return + } + return +} diff --git a/org_test.go b/org_test.go new file mode 100644 index 0000000..ddb2114 --- /dev/null +++ b/org_test.go @@ -0,0 +1,215 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi + +import ( + "fmt" + "reflect" + "strings" + "testing" +) + +func Test_Specify(t *testing.T) { + type args struct { + typeSig string + tag string + sfn func() string + } + tests := []struct { + name string + args args + wantS string + }{ + { + name: "String Type", + args: args{ + typeSig: "S", + tag: "", + sfn: func() string { + return "Test String" + }, + }, + wantS: "S~Test String", + }, + { + name: "String with tag", + args: args{ + typeSig: "S", + tag: "value", + sfn: func() string { + return "Test String" + }, + }, + wantS: "S~value~Test String", + }, + { + name: "String with no function", + args: args{ + typeSig: "S", + tag: "", + sfn: nil, + }, + wantS: "", + }, + { + name: "String without type and Tag", + args: args{ + typeSig: "", + tag: "Testing", + sfn: func() string { + return "Test String" + }, + }, + wantS: "UN~Testing~Test String", + }, + { + name: "String with special Characters", + args: args{ + typeSig: "S", + tag: "", + sfn: func() string { + return "Test String+ with| several~Special Characters" + }, + }, + wantS: "S~Test String%2B with%7C several%7ESpecial Characters", + }, + { + name: "Int Type", + args: args{ + typeSig: "I", + tag: "", + sfn: func() string { + return fmt.Sprintf("%x", 0x3508) + }, + }, + wantS: "I~3508", + }, + { + name: "Error Type", + args: args{ + typeSig: "E", + tag: "", + sfn: func() string { + return fmt.Errorf("custom Error").Error() + }, + }, + wantS: "E~custom Error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := Specify(tt.args.typeSig, tt.args.tag, tt.args.sfn) + if strings.Compare(got, tt.wantS) != 0 { + t.Errorf("error in values got %v want %v", got, tt.wantS) + } + }) + } +} + +func Test_Discover(t *testing.T) { + tests := []struct { + name string + arg string + wantSa []string + wantErr bool + wantInnerError bool + }{ + { + name: "String Type", + arg: "S~Test String", + wantSa: []string{"S", "", "Test String"}, + }, + { + name: "String with tag", + arg: "S~value~Test String", + wantSa: []string{"S", "value", "Test String"}, + }, + { + name: "String with tag with special chars", + arg: "S~value%7C4~Test String", + wantSa: []string{"S", "value|4", "Test String"}, + }, + { + name: "Negative empty string", + arg: "", + wantErr: true, + }, + { + name: "Negative Inner Error string", + arg: "S~value~Test String", + wantErr: true, + wantInnerError: true, + }, + { + name: "Negative corrupt string", + arg: "S~val|ue~Test Str+ing", + wantErr: true, + }, + { + name: "Negative corrupt string2", + arg: "S value Test String", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sa := make([]string, 0, 3) + absorb := func(s1, s2, s3 string) error { + sa = append(sa, s1, s2, s3) + if tt.wantInnerError { + return fmt.Errorf("inner error") + } + return nil + } + err := Discover(tt.arg, absorb) + if (err != nil) != tt.wantErr { + t.Errorf("error in Discover() - %v want error %v", + err, tt.wantErr) + return + } + if !tt.wantErr && !reflect.DeepEqual(tt.wantSa, sa) { + t.Errorf("error in values got %v want %v", sa, tt.wantSa) + } + }) + } +} diff --git a/tppi.go b/tppi.go new file mode 100644 index 0000000..ce858a4 --- /dev/null +++ b/tppi.go @@ -0,0 +1,114 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi + +import ( + "fmt" + "strings" +) + +// Assemble encloses the TPPI contents into the TPPI packet with safeguards. +func Assemble(sa ...string) (s string) { + for _, i := range sa { + // Filter out data with TPPI packet safeguard + i = strings.ReplaceAll(i, "|", "\\x7C") + i = strings.ReplaceAll(i, "+", "\\x2B") + //i = strings.ReplaceAll(i, "~", "\\x7E") + s += i + "|" + } + // Remove the last Pipe Symbol if content is provided + s, _ = strings.CutSuffix(s, "|") + s = "~|" + s + "|~" + return +} + +// Disassemble restores collection of TPPI Contents from the enclosed +// TPPI packet removing the necessary safeguards. +func Disassemble(s string) (sa []string) { + t, _ := strings.CutPrefix(s, "~|") + t, _ = strings.CutSuffix(t, "|~") + ta := strings.Split(t, "|") + sa = make([]string, 0, len(ta)) + for _, i := range ta { + i = strings.ReplaceAll(i, "\\x7C", "|") + i = strings.ReplaceAll(i, "\\x2B", "+") + //i = strings.ReplaceAll(i, "\\x7E", "~") + sa = append(sa, i) + } + return +} + +// ValidPacket verifies if the packet indeed conforms to TPPI protocol or not. +// It also validates the TPPI contents to follow the required guidelines. +func ValidPacket(s string) (err error) { + var sp []string + // Multi Protocol Strings + if strings.Contains(s, "+") { + sp = strings.Split(s, "+") + } else { + sp = append(sp, s) + } + for _, p := range sp { + if !strings.HasPrefix(p, "~|") { + err = fmt.Errorf("not valid packet as missing start indicator") + return + } + if !strings.HasSuffix(p, "|~") { + err = fmt.Errorf("not valid packet as missing end indicator") + } + } + return +} + +// PacketJoin helps to join multiple TPPI packets together. +// This can optionally be run after the Assemble function to bring together +// Multiple TPPI packets together. +func PacketJoin(sa ...string) string { + return strings.Join(sa, "+") +} + +// SplitPacket allows to get back multiple TPPI packets. +// This needs to be run before running the Disassemble function. +func SplitPacket(s string) []string { + return strings.Split(s, "+") +} diff --git a/tppi_test.go b/tppi_test.go new file mode 100644 index 0000000..496f172 --- /dev/null +++ b/tppi_test.go @@ -0,0 +1,261 @@ +// +// ॐ भूर्भुवः स्वः +// तत्स॑वि॒तुर्वरे॑ण्यं॒ +// भर्गो॑ दे॒वस्य॑ धीमहि। +// धियो॒ यो नः॑ प्रचो॒दया॑त्॥ +// +// +// बोसजी के द्वारा रचित टिप्पी अधिलेखन प्रकृया। +// ================================ +// +// एक सरल संचार सहायक और संलग्न तंत्र। +// +// ~~~~~~~~~~~~~~~~~~~~~~~ +// एक रचनात्मक भारतीय उत्पाद। +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// +// Sources +// -------- +// https://github.com/boseji/go-tppi +// +// +// License +// -------- +// +// SPDX: Apache-2.0 +// +// Copyright (C) 2024 Abhijit Bose (aka. Boseji). All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX short identifier: Apache-2.0 + +package tppi + +import ( + "reflect" + "strings" + "testing" +) + +func Test_Assemble(t *testing.T) { + tests := []struct { + name string + args []string + wantS string + }{ + { + name: "Basic test of Assembly", + args: []string{ + "P1", + "P2", + }, + wantS: "~|P1|P2|~", + }, + { + name: "Assemble string containing special chars", + args: []string{ + "P1|", + "P~2", + }, + wantS: "~|P1\\x7C|P~2|~", + }, + { + name: "Assemble string containing multiple special chars", + args: []string{ + "Pa~rt1|", + "P|+art~2", + }, + wantS: "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + { + name: "Blank contents", + args: []string{}, + wantS: "~||~", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := Assemble(tt.args...) + if strings.Compare(got, tt.wantS) != 0 { + t.Errorf("error in values got %v want %v", got, tt.wantS) + } + }) + } +} + +func Test_Disassemble(t *testing.T) { + tests := []struct { + name string + args string + wantSa []string + }{ + { + name: "Basic test of Assembly", + args: "~|P1|P2|~", + wantSa: []string{ + "P1", + "P2", + }, + }, + { + name: "Assemble string containing special chars", + args: "~|P1\\x7C|P~2|~", + wantSa: []string{ + "P1|", + "P~2", + }, + }, + { + name: "Assemble string containing multiple special chars", + args: "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + wantSa: []string{ + "Pa~rt1|", + "P|+art~2", + }, + }, + { + name: "Blank contents", + args: "", + wantSa: []string{""}, + }, + { + name: "Blank packet", + args: "~||~", + wantSa: []string{""}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := Disassemble(tt.args) + if !reflect.DeepEqual(got, tt.wantSa) { + t.Errorf("error in values got %v want %v", got, tt.wantSa) + } + }) + } +} + +func Test_ValidPacket(t *testing.T) { + tests := []struct { + name string + arg string + wantErr bool + }{ + { + name: "Basic Single Packet", + arg: "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + { + name: "Dual Packets", + arg: "~|P1\\x7C|P~2|~+~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + { + name: "Error Single Packet1", + arg: "~Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + wantErr: true, + }, + { + name: "Error Single Packet2", + arg: "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|", + wantErr: true, + }, + { + name: "Error Single Packet3", + arg: "~|Pa~rt1\\x7C|~P+\\x2Bart~2|~", + wantErr: true, + }, + { + name: "Error Single Packet4", + arg: "~|Pa~rt1\\x7C+P\\x7C\\x2Bart~2|~", + wantErr: true, + }, + { + name: "Error Single Packet5", + arg: "~|Pa~rt1\\x7C|~~|+~|P\\x7C\\x2Bart~2|~", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidPacket(tt.arg) + if (err != nil) != tt.wantErr { + t.Errorf("error ValidPacket() got %v want error %v", + err, tt.wantErr) + } + }) + } +} + +func Test_PacketJoin(t *testing.T) { + tests := []struct { + name string + args []string + wantS string + }{ + { + name: "Join a single packet", + args: []string{ + "~||~", + }, + wantS: "~||~", + }, + { + name: "Join two packet", + args: []string{ + "~||~", + "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + wantS: "~||~+~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := PacketJoin(tt.args...) + if strings.Compare(got, tt.wantS) != 0 { + t.Errorf("error in values got %v want %v", got, tt.wantS) + } + }) + } +} + +func Test_PacketSplit(t *testing.T) { + tests := []struct { + name string + arg string + wantSa []string + }{ + { + name: "Join a single packet", + arg: "~||~", + wantSa: []string{ + "~||~", + }, + }, + { + name: "Join two packet", + arg: "~||~+~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + wantSa: []string{ + "~||~", + "~|Pa~rt1\\x7C|P\\x7C\\x2Bart~2|~", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := SplitPacket(tt.arg) + if !reflect.DeepEqual(got, tt.wantSa) { + t.Errorf("error in values got %v want %v", got, tt.wantSa) + } + }) + } +}