msgpack-go

Message Pack Encoder/Decoder for Golang
git clone git://git.lair.cx/msgpack-go
Log | Files | Refs | LICENSE

commit abed4d39fd64a049f5f80695216434b476766ae8
Author: Yongbin Kim <iam@yongbin.kim>
Date:   Tue, 13 Sep 2022 16:13:21 +0900

migrated

Signed-off-by: Yongbin Kim <iam@yongbin.kim>

Diffstat:
A.gitignore | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALICENSE | 21+++++++++++++++++++++
Adecode.go | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adecode_test.go | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adecode_unsafe.go | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adecode_unsafe_test.go | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adecode_value.go | 594+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aencode.go | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aencode_test.go | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aencode_value.go | 235+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ago.mod | 5+++++
Ago.sum | 2++
Amsgpack_test.go | 286+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astr16_test.txt | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astr32_test.txt | 249+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atimestamp.go | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Auuid.go | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Auuid_test.go | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Avalue.go | 23+++++++++++++++++++++++
19 files changed, 2617 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,216 @@ +# Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,goland,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,goland,visualstudiocode + +### GoLand ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### GoLand Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope +.vscode/*.code-snippets + +# Ignore code-workspaces +*.code-workspace + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/linux,macos,windows,goland,visualstudiocode +n +\ No newline at end of file diff --git a/LICENSE b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Yongbin Kim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/decode.go b/decode.go @@ -0,0 +1,147 @@ +package msgpack + +import ( + "io" +) + +func Unmarshal(p []byte, v interface{}) error { + return NewDecoder(nil, p).Decode(v) +} + +type Decoder struct { + r io.Reader + buf []byte + length int + cursor int + err error +} + +// NewDecoder returns a new decoder instance. +// +// Decoder takes reader and buffer. +// r can be nil. when r is nil, decoder uses buf as data source. +// +// It panics when both r and buf are nil. +func NewDecoder(r io.Reader, buf []byte) *Decoder { + d := &Decoder{} + d.Reset(r, buf) + return d +} + +// Reset resets the decoder. if both r and buf are nil, it panics. +func (d *Decoder) Reset(r io.Reader, buf []byte) { + if r == nil && len(buf) == 0 { + panic("core/msgpack: decoder: no source is provided") + } + + if len(buf) == 0 { + buf = make([]byte, 512) + } + + *d = Decoder{ + r: r, + buf: buf, + } + + if r == nil { + d.length = len(buf) + } +} + +// Decode decodes input from reader or buffer to value. +func (d *Decoder) Decode(v interface{}) error { + return d.decode(v) +} + +func (d *Decoder) decode(v interface{}) error { + switch v := v.(type) { + case *bool: + return d.Bool(v) + case *int: + return d.Int(v) + case *int8: + return d.Int8(v) + case *int16: + return d.Int16(v) + case *int32: + return d.Int32(v) + case *int64: + return d.Int64(v) + case *uint: + return d.Uint(v) + case *uint8: + return d.Uint8(v) + case *uint16: + return d.Uint16(v) + case *uint32: + return d.Uint32(v) + case *uint64: + return d.Uint64(v) + case *float32: + return d.Float32(v) + case *float64: + return d.Float64(v) + case *string: + return d.String(v) + case *[]byte: + return d.Binary(v) + case Array: + return d.Array(v) + case Map: + return d.Map(v) + case Extension: + return d.Ext(v) + default: + panic("unsupported value") + } +} + +func (d *Decoder) read(p []byte) (int, error) { + if len(p) == 0 { + return 0, nil + } + + // no empty space in buffer + if d.length == d.cursor { + if d.r == nil { + return 0, io.EOF + } + + if len(p) >= len(d.buf) { + return d.r.Read(p) + } + + n, err := d.r.Read(d.buf) + if err != nil { + return 0, err + } + + d.cursor = 0 + d.length = n + } + + n := copy(p, d.buf[d.cursor:d.length]) + d.cursor += n + + if d.r != nil && n < len(p) { + n2, err := d.read(p[n:]) + if err != nil && err != io.EOF { + return n, err + } + n += n2 + } + + return n, nil +} + +func (d *Decoder) readByte() (byte, error) { + buf := make([]byte, 1) + n, err := d.read(buf) + if err != nil { + return 0, err + } + if n == 0 { + return 0, io.EOF + } + return buf[0], nil +} diff --git a/decode_test.go b/decode_test.go @@ -0,0 +1,188 @@ +package msgpack + +import ( + "bytes" + "fmt" + "io" + "reflect" + "testing" + "time" +) + +func TestRead(t *testing.T) { + var in = bytes.Repeat([]byte{'_'}, 256) + + testfn := func(useReader bool) func(t *testing.T) { + var d *Decoder + if useReader { + d = NewDecoder(bytes.NewReader(in), make([]byte, 0, 128)) + } else { + d = NewDecoder(nil, in) + } + + return func(t *testing.T) { + // up to 16 bytes (total 136 bytes) + for i := 1; i <= 16; i++ { + buf := make([]byte, i) + n, err := d.read(buf) + if err != nil { + t.Errorf("d.read(%d bytes buffer) returns an error: %s", i, err.Error()) + return + } + if n != i || !bytes.Equal(buf, bytes.Repeat([]byte{'_'}, i)) { + t.Errorf("d.read() returns %v, want: %v", buf, bytes.Repeat([]byte{'_'}, i)) + return + } + } + + // big buffer + buf := make([]byte, 256) + n, err := d.read(buf) + if err != nil { + t.Errorf("d.read() returns an error: %s", err.Error()) + return + } + if n != 120 || !bytes.Equal(buf[:120], bytes.Repeat([]byte{'_'}, 120)) { + t.Errorf("d.read() returns %d, %v, want: %d, %v", n, buf, 120, bytes.Repeat([]byte{'_'}, 120)) + return + } + + _, err = d.read(buf) + if err != io.EOF { + t.Errorf("d.read() returns an error: %s, want: io.Nil", err.Error()) + return + } + } + } + + t.Run("buffer-only", testfn(false)) + t.Run("with-reader", testfn(true)) +} + +func TestDecodeNil(t *testing.T) { + d := NewDecoder(nil, []byte{0xc0, '_'}) + + isNil, err := d.NextIsNil() + if err != nil { + t.Errorf("d.NextIsNil() returns an error: %s", err.Error()) + return + } + if !isNil { + t.Errorf("d.NextIsNil() returns false, want: true") + return + } + + if err := d.Nil(); err != nil { + t.Errorf("d.Nil() returns error: %s", err.Error()) + } + + var p = make([]byte, 1) + if err := d.Raw(p); err != nil { + t.Errorf("d.Raw() returns error: %s", err.Error()) + } + if !bytes.Equal(p, []byte{'_'}) { + t.Errorf("d.Nil() does not skip nil byte") + } +} + +func TestDecode(t *testing.T) { + d := NewDecoder(nil, []byte{' '}) + + for _, test := range testCases { + d.Reset(nil, test.encoded) + + var err error + var got interface{} + switch test.decoded.(type) { + case bool: + var v bool + err = d.Bool(&v) + got = v + case int: + var v int + err = d.Int(&v) + got = v + case int8: + var v int8 + err = d.Int8(&v) + got = v + case int16: + var v int16 + err = d.Int16(&v) + got = v + case int32: + var v int32 + err = d.Int32(&v) + got = v + case int64: + var v int64 + err = d.Int64(&v) + got = v + case uint: + var v uint + err = d.Uint(&v) + got = v + case uint8: + var v uint8 + err = d.Uint8(&v) + got = v + case uint16: + var v uint16 + err = d.Uint16(&v) + got = v + case uint32: + var v uint32 + err = d.Uint32(&v) + got = v + case uint64: + var v uint64 + err = d.Uint64(&v) + got = v + case float32: + var v float32 + err = d.Float32(&v) + got = v + case float64: + var v float64 + err = d.Float64(&v) + got = v + case string: + var v string + err = d.String(&v) + got = v + case []byte: + var v []byte + err = d.Binary(&v) + got = v + case Array: + var v testArray + err = d.Array(&v) + got = &v + case Map: + var v testMap + err = d.Map(&v) + got = &v + case Extension: + var v testExt + err = d.Ext(&v) + got = &v + case time.Time: + var v Timestamp + err = d.Ext(&v) + got = (&v).Time() + default: + panic(fmt.Sprintf("invalid test input type: %s", reflect.TypeOf(test.decoded).Name())) + } + + if err != nil { + t.Errorf("d.%s(%v) returns error: %s", reflect.TypeOf(test.decoded).Name(), test.encoded, err.Error()) + t.FailNow() + } + + if !reflect.DeepEqual(got, test.decoded) { + fmt.Println(test, got) + t.Errorf("d.%s(%v) returns %v, want: %v", reflect.TypeOf(test.decoded).Name(), test.encoded, got, test.decoded) + t.FailNow() + } + } +} diff --git a/decode_unsafe.go b/decode_unsafe.go @@ -0,0 +1,93 @@ +package msgpack + +import ( + "io" +) + +type UnsafeDecoder struct { + *Decoder +} + +func NewUnsafeDecoder(r io.Reader, buf []byte) *UnsafeDecoder { + return &UnsafeDecoder{NewDecoder(r, buf)} +} + +func (d *UnsafeDecoder) Reader() io.Reader { + return d.r +} + +func (d *UnsafeDecoder) SetReader(r io.Reader) { + d.r = r +} + +func (d *UnsafeDecoder) Buffer() []byte { + return d.buf +} + +func (d *UnsafeDecoder) SetBuffer(p []byte) { + d.buf = p +} + +func (d *UnsafeDecoder) BufferLength() int { + return d.length +} + +func (d *UnsafeDecoder) SetBufferLength(n int) { + d.length = n +} + +func (d *UnsafeDecoder) CursorPosition() int { + return d.cursor +} + +func (d *UnsafeDecoder) SetCursorPosition(n int) { + d.cursor = n +} + +func (d *UnsafeDecoder) ReadBuffer(p []byte) (int, error) { + return d.read(p) +} + +func (d *UnsafeDecoder) PreviewBuffer(p []byte) (int, error) { + if len(p) == 0 { + return 0, nil + } + + if d.length-d.cursor < len(p) && d.r != nil { + err := d.ExpandBuffer(len(p)) + if err != nil { + return 0, err + } + } + + n := len(p) + if d.length-d.cursor < n { + n = d.length - d.cursor + } + + copy(p[:n], d.buf[d.cursor:d.cursor+n]) + return n, nil +} + +func (d *UnsafeDecoder) ExpandBuffer(n int) error { + if d.r == nil { + return nil + } + + buf := make([]byte, d.length+n) + + // Read from reader + rn, err := d.r.Read(buf[d.length:]) + if err != nil { + return err + } + buf = buf[:d.length+rn] + + // Copy from original + copy(buf[:d.length], d.buf) + + d.buf = buf + d.length += rn + + return nil +} diff --git a/decode_unsafe_test.go b/decode_unsafe_test.go @@ -0,0 +1,74 @@ +package msgpack + +import ( + "bytes" + "testing" +) + +func TestUnsafeDecoder_ExpandBuffer(t *testing.T) { + tests := []struct { + name string + decoder *Decoder + n int + want []byte + wantErr bool + }{ + { + "initial state", + NewDecoder( + bytes.NewReader([]byte("Hello, World!")), + make([]byte, 5), + ), + 5, + []byte("Hello"), + false, + }, + { + "double the buffer", + &Decoder{ + r: bytes.NewReader([]byte(", World!")), + buf: []byte("Hello"), + length: 5, + cursor: 0, + }, + 5, + []byte("Hello, Wor"), + false, + }, + { + "overflow", + NewDecoder( + bytes.NewReader([]byte("Hello, World!")), + make([]byte, 5), + ), + 42, + []byte("Hello, World!"), + false, + }, + { + "no reader", + NewDecoder( + nil, + []byte("Hello, World!"), + ), + 5, + []byte("Hello, World!"), + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &UnsafeDecoder{ + Decoder: tt.decoder, + } + err := d.ExpandBuffer(tt.n) + if (err != nil) != tt.wantErr { + t.Errorf("ExpandBuffer() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !bytes.Equal(d.buf, tt.want) { + t.Errorf("ExpandBuffer() d.buf = %q, want %q", string(d.buf), string(tt.want)) + } + }) + } +} diff --git a/decode_value.go b/decode_value.go @@ -0,0 +1,594 @@ +package msgpack + +import ( + "fmt" + "io" + "math" + + "github.com/google/uuid" +) + +type ErrInvalidHeader struct { + name string + got []byte +} + +func (err *ErrInvalidHeader) Error() string { + return fmt.Sprintf("msgpack: invalid %s header; got: %v", err.name, err.got) +} + +type ErrUnexpectedEOF struct{} + +func (err *ErrUnexpectedEOF) Error() string { + return "msgpack: unexpected EOF" +} + +func (err *ErrUnexpectedEOF) Unwrap() error { + return io.EOF +} + +func (d *Decoder) NextIsNil() (bool, error) { + if d.length == d.cursor { + n, err := d.r.Read(d.buf) + if err != nil { + return false, err + } + d.cursor = 0 + d.length = n + } + return d.buf[d.cursor] == 0xc0, nil +} + +func (d *Decoder) Nil() error { + p, err := d.readByte() + if err != nil { + return err + } + if p != 0xc0 { + return &ErrInvalidHeader{"nil", []byte{p}} + } + return nil +} + +func (d *Decoder) Bool(v *bool) error { + p, err := d.readByte() + if err != nil { + return err + } + switch p { + case 0xc2: + *v = true + case 0xc3: + *v = false + default: + return &ErrInvalidHeader{"bool", []byte{p}} + } + return nil +} + +func (d *Decoder) Int(v *int) error { + sign, err := d.readByte() + if err != nil { + return err + } + + switch sign { + case 0xcc: + n, err := d.readByte() + if err != nil { + return err + } + *v = int(uint8(n)) + case 0xcd: + n, err := d.deserialize16() + if err != nil { + return err + } + *v = int(uint16(n)) + case 0xce: + n, err := d.deserialize32() + if err != nil { + return err + } + *v = int(uint32(n)) + case 0xcf: + n, err := d.deserialize64() + if err != nil { + return err + } + *v = int(uint64(n)) + case 0xd0: + n, err := d.readByte() + if err != nil { + return err + } + *v = int(int8(n)) + case 0xd1: + n, err := d.deserialize16() + if err != nil { + return err + } + *v = int(int16(n)) + case 0xd2: + n, err := d.deserialize32() + if err != nil { + return err + } + *v = int(int32(n)) + case 0xd3: + n, err := d.deserialize64() + if err != nil { + return err + } + *v = int(int64(n)) + default: + if sign>>7 == 0 || sign>>5 == 7 { + *v = int(int8(sign)) + return nil + } + return &ErrInvalidHeader{"int", []byte{sign}} + } + return nil +} + +func (d *Decoder) Int8(v *int8) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xd0 { + return &ErrInvalidHeader{"int8", []byte{sign}} + } + n, err := d.readByte() + if err != nil { + return err + } + *v = int8(n) + return nil +} + +func (d *Decoder) Int16(v *int16) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xd1 { + return &ErrInvalidHeader{"int8", []byte{sign}} + } + n, err := d.deserialize16() + if err != nil { + return err + } + *v = int16(n) + return nil +} + +func (d *Decoder) Int32(v *int32) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xd2 { + return &ErrInvalidHeader{"int8", []byte{sign}} + } + n, err := d.deserialize32() + if err != nil { + return err + } + *v = int32(n) + return nil +} + +func (d *Decoder) Int64(v *int64) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xd3 { + return &ErrInvalidHeader{"int8", []byte{sign}} + } + n, err := d.deserialize64() + if err != nil { + return err + } + *v = int64(n) + return nil +} + +func (d *Decoder) Uint(v *uint) error { + sign, err := d.readByte() + if err != nil { + return err + } + + switch sign { + case 0xcc: + n, err := d.readByte() + if err != nil { + return err + } + *v = uint(n) + case 0xcd: + n, err := d.deserialize16() + if err != nil { + return err + } + *v = uint(n) + case 0xce: + n, err := d.deserialize32() + if err != nil { + return err + } + *v = uint(n) + case 0xcf: + n, err := d.deserialize64() + if err != nil { + return err + } + *v = uint(n) + default: + if sign>>7 == 0 { + *v = uint(sign) + return nil + } + return &ErrInvalidHeader{"uint", []byte{sign}} + } + return nil +} + +func (d *Decoder) Uint8(v *uint8) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xcc { + return &ErrInvalidHeader{"uint8", []byte{sign}} + } + n, err := d.readByte() + if err != nil { + return err + } + *v = uint8(n) + return nil +} + +func (d *Decoder) Uint16(v *uint16) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xcd { + return &ErrInvalidHeader{"uint16", []byte{sign}} + } + n, err := d.deserialize16() + if err != nil { + return err + } + *v = uint16(n) + return nil +} + +func (d *Decoder) Uint32(v *uint32) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xce { + return &ErrInvalidHeader{"uint32", []byte{sign}} + } + n, err := d.deserialize32() + if err != nil { + return err + } + *v = uint32(n) + return nil +} + +func (d *Decoder) Uint64(v *uint64) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xcf { + return &ErrInvalidHeader{"uint64", []byte{sign}} + } + n, err := d.deserialize64() + if err != nil { + return err + } + *v = uint64(n) + return nil +} + +func (d *Decoder) Float32(v *float32) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xca { + return &ErrInvalidHeader{"float32", []byte{sign}} + } + n, err := d.deserialize32() + if err != nil { + return err + } + *v = math.Float32frombits(n) + return nil +} + +func (d *Decoder) Float64(v *float64) error { + sign, err := d.readByte() + if err != nil { + return err + } + if sign != 0xcb { + return &ErrInvalidHeader{"float64", []byte{sign}} + } + n, err := d.deserialize64() + if err != nil { + return err + } + *v = math.Float64frombits(n) + return nil +} + +func (d *Decoder) String(v *string) error { + sign, err := d.readByte() + if err != nil { + return err + } + + var n int + switch sign { + case 0xd9: + p, err := d.readByte() + if err != nil { + return err + } + n = int(p) + case 0xda: + p, err := d.deserialize16() + if err != nil { + return err + } + n = int(p) + case 0xdb: + p, err := d.deserialize32() + if err != nil { + return err + } + n = int(p) + default: + if sign>>5 != 5 { + return &ErrInvalidHeader{"string", []byte{sign}} + } + n = int(sign & 0x1f) + } + + buf := make([]byte, n) + read, err := d.read(buf) + if err != nil && err != io.EOF { + return err + } + if read < n { + return &ErrUnexpectedEOF{} + } + + *v = string(buf) + return nil +} + +func (d *Decoder) Binary(v *[]byte) error { + sign, err := d.readByte() + if err != nil { + return err + } + + var n int + switch sign { + case 0xc4: + p, err := d.readByte() + if err != nil { + return err + } + n = int(p) + case 0xc5: + p, err := d.deserialize16() + if err != nil { + return err + } + n = int(p) + case 0xc6: + p, err := d.deserialize32() + if err != nil { + return err + } + n = int(p) + default: + return &ErrInvalidHeader{"binary", []byte{sign}} + } + + buf := make([]byte, n) + read, err := d.read(buf) + if err != nil && err != io.EOF { + return err + } + if read < n { + return &ErrUnexpectedEOF{} + } + + *v = buf + return nil +} + +func (d *Decoder) Array(v Array) error { + sign, err := d.readByte() + if err != nil { + return err + } + + var n int + switch sign { + case 0xdc: + p, err := d.deserialize16() + if err != nil { + return err + } + n = int(p) + case 0xdd: + p, err := d.deserialize32() + if err != nil { + return err + } + n = int(p) + default: + if sign>>4 != 9 { + return &ErrInvalidHeader{"array", []byte{sign}} + } + n = int(sign & 0x0f) + } + + err = v.DecodeMsgpackArray(d, n) + if err != nil { + return err + } + + return nil +} + +func (d *Decoder) Map(v Map) error { + sign, err := d.readByte() + if err != nil { + return err + } + + var n int + switch sign { + case 0xde: + p, err := d.deserialize16() + if err != nil { + return err + } + n = int(p) + case 0xdf: + p, err := d.deserialize32() + if err != nil { + return err + } + n = int(p) + default: + if sign>>4 != 8 { + return &ErrInvalidHeader{"string", []byte{sign}} + } + n = int(sign & 0x0f) + } + + err = v.DecodeMsgpackMap(d, n) + if err != nil { + return err + } + + return nil +} + +func (d *Decoder) UUID(v *uuid.UUID) error { + w := &UUID{} + + err := d.Ext(w) + if err != nil { + return err + } + + *v = w.UUID + return nil +} + +func (d *Decoder) Ext(v Extension) error { + sign, err := d.readByte() + if err != nil { + return err + } + + var n int + switch sign { + case 0xd4: + n = 1 + case 0xd5: + n = 2 + case 0xd6: + n = 4 + case 0xd7: + n = 8 + case 0xd8: + n = 16 + case 0xc7: + p, err := d.readByte() + if err != nil { + return err + } + n = int(p) + case 0xc8: + p, err := d.deserialize16() + if err != nil { + return err + } + n = int(p) + case 0xc9: + p, err := d.deserialize32() + if err != nil { + return err + } + n = int(p) + } + + typ, err := d.readByte() + if err != nil { + return err + } + + return v.DecodeMsgpackExt(d, int8(typ), n) +} + +func (d *Decoder) Raw(v []byte) error { + _, err := d.read(v) + return err +} + +func (d *Decoder) deserialize16() (uint16, error) { + var p = make([]byte, 2) + n, err := d.read(p) + if n != 2 || err == io.EOF { + return 0, &ErrUnexpectedEOF{} + } + if err != nil { + return 0, err + } + return uint16(p[1]) | uint16(p[0])<<8, nil +} + +func (d *Decoder) deserialize32() (uint32, error) { + var p = make([]byte, 4) + n, err := d.read(p) + if n != 4 || err == io.EOF { + return 0, &ErrUnexpectedEOF{} + } + if err != nil { + return 0, err + } + return uint32(p[3]) | uint32(p[2])<<8 | uint32(p[1])<<16 | + uint32(p[0])<<24, nil +} + +func (d *Decoder) deserialize64() (uint64, error) { + var p = make([]byte, 8) + n, err := d.read(p) + if n != 8 || err == io.EOF { + return 0, &ErrUnexpectedEOF{} + } + if err != nil { + return 0, err + } + return uint64(p[7]) | uint64(p[6])<<8 | uint64(p[5])<<16 | + uint64(p[4])<<24 | uint64(p[3])<<32 | uint64(p[2])<<40 | + uint64(p[1])<<48 | uint64(p[0])<<56, nil +} diff --git a/encode.go b/encode.go @@ -0,0 +1,101 @@ +package msgpack + +import "github.com/google/uuid" + +func Marshal(v interface{}) []byte { + // TODO: Make encoder pool + return NewEncoder().Encode(v) +} + +type Encoder struct { + buf []byte +} + +func NewEncoder() *Encoder { + return &Encoder{ + buf: make([]byte, 0, 512), + } +} + +func (e *Encoder) Reset() { + e.buf = e.buf[:0] +} + +func (e *Encoder) Encode(v interface{}) []byte { + e.Reset() + e.encode(v) + return e.buf +} + +func (e *Encoder) encode(v interface{}) { + if v == nil { + e.Nil() + return + } + switch v := v.(type) { + case bool: + e.Bool(v) + case int: + e.Int(v) + case int8: + e.Int8(v) + case int16: + e.Int16(v) + case int32: + e.Int32(v) + case int64: + e.Int64(v) + case uint: + e.Uint(v) + case uint8: + e.Uint8(v) + case uint16: + e.Uint16(v) + case uint32: + e.Uint32(v) + case uint64: + e.Uint64(v) + case float32: + e.Float32(v) + case float64: + e.Float64(v) + case string: + e.String(v) + case []byte: + e.Binary(v) + case Array: + e.Array(v) + case Map: + e.Map(v) + case uuid.UUID: + e.Ext(&UUID{v}) + case Extension: + e.Ext(v) + default: + // oh... + panic("unsupported value") + } +} + +func (e *Encoder) grow(n int) { + if cap(e.buf)-len(e.buf) > n { + return + } + newbuf := make([]byte, len(e.buf), cap(e.buf)*2+n) + copy(newbuf, e.buf) + e.buf = newbuf +} + +func (e *Encoder) serialize16(v uint16) { + e.buf = append(e.buf, byte(v>>8), byte(v)) +} + +func (e *Encoder) serialize32(v uint32) { + e.buf = append(e.buf, byte(v>>24), byte(v>>16), byte(v>>8), + byte(v)) +} + +func (e *Encoder) serialize64(v uint64) { + e.buf = append(e.buf, byte(v>>56), byte(v>>48), byte(v>>40), + byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} diff --git a/encode_test.go b/encode_test.go @@ -0,0 +1,75 @@ +package msgpack + +import ( + "bytes" + "reflect" + "testing" + "time" +) + +func TestEncodeNil(t *testing.T) { + e := NewEncoder() + e.Nil() + if !bytes.Equal(e.buf, []byte{0xc0}) { + t.Errorf("e.Nil() returns %v, want: [0xc0]", e.buf) + } +} + +func TestEncode(t *testing.T) { + e := NewEncoder() + + for _, test := range testCases { + e.Reset() + + switch v := test.decoded.(type) { + case bool: + e.Bool(v) + case int: + e.Int(v) + case int8: + e.Int8(v) + case int16: + e.Int16(v) + case int32: + e.Int32(v) + case int64: + e.Int64(v) + case uint: + e.Uint(v) + case uint8: + e.Uint8(v) + case uint16: + e.Uint16(v) + case uint32: + e.Uint32(v) + case uint64: + e.Uint64(v) + case float32: + e.Float32(v) + case float64: + e.Float64(v) + case string: + e.String(v) + case []byte: + e.Binary(v) + case Array: + e.Array(v) + case Map: + e.Map(v) + case Extension: + e.Ext(v) + case time.Time: + e.Ext(NewTimestamp(v)) + } + + if !bytes.Equal(e.buf, test.encoded) { + t.Errorf( + "e.%s(%v) returns %v, want: %v", + reflect.TypeOf(test.decoded).Name(), + test.decoded, + e.buf, + test.encoded, + ) + } + } +} diff --git a/encode_value.go b/encode_value.go @@ -0,0 +1,235 @@ +package msgpack + +import "math" + +func (e *Encoder) Nil() { + e.grow(1) + e.buf = append(e.buf, 0xc0) +} + +func (e *Encoder) Bool(v bool) { + e.grow(1) + if v { + e.buf = append(e.buf, 0xc2) + } else { + e.buf = append(e.buf, 0xc3) + } +} + +func (e *Encoder) Int(v int) { + switch { + case v > 0xffffffff: + e.Uint64(uint64(v)) + case v > 0xffff: + e.Uint32(uint32(v)) + case v > 0xff: + e.Uint16(uint16(v)) + case v > 0x7f: + e.Uint8(uint8(v)) + case v < -0x80000000: + e.Int64(int64(v)) + case v < -0x8000: + e.Int32(int32(v)) + case v < -0x80: + e.Int16(int16(v)) + case v < -32: + e.Int8(int8(v)) + default: + e.grow(1) + e.buf = append(e.buf, byte(v)) + } +} + +func (e *Encoder) Int8(v int8) { + e.grow(2) + e.buf = append(e.buf, 0xd0, byte(v)) +} + +func (e *Encoder) Int16(v int16) { + e.grow(3) + e.buf = append(e.buf, 0xd1) + e.serialize16(uint16(v)) +} + +func (e *Encoder) Int32(v int32) { + e.grow(5) + e.buf = append(e.buf, 0xd2) + e.serialize32(uint32(v)) +} + +func (e *Encoder) Int64(v int64) { + e.grow(9) + e.buf = append(e.buf, 0xd3) + e.serialize64(uint64(v)) +} + +func (e *Encoder) Uint(v uint) { + switch { + case v > 0xffffffff: + e.Uint64(uint64(v)) + case v > 0xffff: + e.Uint32(uint32(v)) + case v > 0xff: + e.Uint16(uint16(v)) + case v > 0x7f: + e.Uint8(uint8(v)) + default: + e.grow(1) + e.buf = append(e.buf, byte(v)) + } +} + +func (e *Encoder) Uint8(v uint8) { + e.grow(2) + e.buf = append(e.buf, 0xcc, byte(v)) +} + +func (e *Encoder) Uint16(v uint16) { + e.grow(3) + e.buf = append(e.buf, 0xcd) + e.serialize16(v) +} + +func (e *Encoder) Uint32(v uint32) { + e.grow(5) + e.buf = append(e.buf, 0xce) + e.serialize32(v) +} + +func (e *Encoder) Uint64(v uint64) { + e.grow(9) + e.buf = append(e.buf, 0xcf) + e.serialize64(v) +} + +func (e *Encoder) Float32(v float32) { + b := math.Float32bits(v) + e.grow(5) + e.buf = append(e.buf, 0xca) + e.serialize32(b) +} + +func (e *Encoder) Float64(v float64) { + b := math.Float64bits(v) + e.grow(9) + e.buf = append(e.buf, 0xcb) + e.serialize64(b) +} + +func (e *Encoder) String(s string) { + switch { + case len(s) > 0xFFFF: + e.grow(len(s) + 5) + e.buf = append(e.buf, 0xdb) + e.serialize32(uint32(len(s))) + case len(s) > 0xFF: + e.grow(len(s) + 3) + e.buf = append(e.buf, 0xda) + e.serialize16(uint16(len(s))) + case len(s) > 31: + e.grow(len(s) + 2) + e.buf = append(e.buf, 0xd9, byte(len(s))) + default: + e.grow(len(s) + 1) + e.buf = append(e.buf, byte(0xa0|len(s))) + } + e.buf = append(e.buf, s...) +} + +func (e *Encoder) Binary(s []byte) { + switch { + case len(s) > 0xFFFF: + e.grow(len(s) + 5) + e.buf = append(e.buf, 0xc6) + e.serialize32(uint32(len(s))) + case len(s) > 0xFF: + e.grow(len(s) + 3) + e.buf = append(e.buf, 0xc5) + e.serialize16(uint16(len(s))) + default: + e.grow(len(s) + 2) + e.buf = append(e.buf, 0xc4, byte(len(s))) + } + e.buf = append(e.buf, s...) +} + +func (e *Encoder) Array(v Array) { + n := v.Len() + switch { + case n > 0xFFFF: + e.grow(5) + e.buf = append(e.buf, 0xdd) + e.serialize32(uint32(n)) + case n > 15: + e.grow(3) + e.buf = append(e.buf, 0xdc) + e.serialize16(uint16(n)) + default: + e.grow(1) + e.buf = append(e.buf, byte(0x90|n)) + } + + v.EncodeMsgpackArray(e) +} + +func (e *Encoder) Map(v Map) { + n := v.Size() + switch { + case n > 0xFFFF: + e.grow(5) + e.buf = append(e.buf, 0xdf) + e.serialize32(uint32(n)) + case n > 15: + e.grow(3) + e.buf = append(e.buf, 0xde) + e.serialize16(uint16(n)) + default: + e.grow(1) + e.buf = append(e.buf, byte(0x80|n)) + } + + v.EncodeMsgpackMap(e) +} + +func (e *Encoder) Ext(v Extension) { + var ( + typ = byte(v.Type()) + n = v.Size() + ) + switch { + case n == 1: + e.grow(3) + e.buf = append(e.buf, 0xd4, typ) + case n == 2: + e.grow(4) + e.buf = append(e.buf, 0xd5, typ) + case n == 4: + e.grow(6) + e.buf = append(e.buf, 0xd6, typ) + case n == 8: + e.grow(10) + e.buf = append(e.buf, 0xd7, typ) + case n == 16: + e.grow(18) + e.buf = append(e.buf, 0xd8, typ) + case n > 0xFFFF: + e.grow(6 + n) + e.buf = append(e.buf, 0xc9) + e.serialize32(uint32(n)) + e.buf = append(e.buf, typ) + case n > 0xFF: + e.grow(4 + n) + e.buf = append(e.buf, 0xc8) + e.serialize16(uint16(n)) + e.buf = append(e.buf, typ) + default: + e.grow(3 + n) + e.buf = append(e.buf, 0xc7, byte(n), typ) + } + v.EncodeMsgpackExt(e) +} + +func (e *Encoder) Raw(p []byte) { + e.grow(len(p)) + e.buf = append(e.buf, p...) +} diff --git a/go.mod b/go.mod @@ -0,0 +1,5 @@ +module go.lair.cx/msgpack + +go 1.18 + +require github.com/google/uuid v1.3.0 diff --git a/go.sum b/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/msgpack_test.go b/msgpack_test.go @@ -0,0 +1,286 @@ +package msgpack + +import ( + "bytes" + "fmt" + "time" + + _ "embed" +) + +//go:embed str16_test.txt +var str16test string + +//go:embed str32_test.txt +var str32test string + +type testCase struct { + decoded interface{} + encoded []byte +} + +func makeStringCase(s string, prefix []byte) testCase { + return testCase{ + decoded: s, + encoded: append(prefix, s...), + } +} + +func makeBinaryCase(s []byte, prefix []byte) testCase { + return testCase{ + decoded: s, + encoded: append(prefix, s...), + } +} + +func makeMapCase(n int, prefix []byte) testCase { + var buf = prefix + for i := 0; i < n; i++ { + buf = append( + buf, + 0xcf, + byte(i>>56), byte(i>>48), byte(i>>40), byte(i>>32), + byte(i>>24), byte(i>>16), byte(i>>8), byte(i), + 1, + ) + } + return testCase{newTestMap(n), buf} +} + +var testCases = []testCase{ + // bool + {true, []byte{0xc2}}, + {false, []byte{0xc3}}, + + // fixint + {int(0), []byte{0}}, + {int(2), []byte{2}}, + {int(-1), []byte{0xff}}, + {int(-32), []byte{0xe0}}, + + // positive int + {int(255), []byte{0xcc, 0xff}}, + {int(256), []byte{0xcd, 0x01, 0x00}}, + {int(65536), []byte{0xce, 0x00, 0x01, 0x00, 0x00}}, + {int(4294967296), []byte{0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}}, + + // negative int + {int(-128), []byte{0xd0, 0x80}}, + {int(-129), []byte{0xd1, 0xff, 0x7f}}, + {int(-256), []byte{0xd1, 0xff, 0x00}}, + {int(-32769), []byte{0xd2, 0xff, 0xff, 0x7f, 0xff}}, + {int(-2147483649), []byte{0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff}}, + + // sized int + {int8(127), []byte{0xd0, 0x7f}}, + {int8(-128), []byte{0xd0, 0x80}}, + {int16(32767), []byte{0xd1, 0x7f, 0xff}}, + {int16(-32768), []byte{0xd1, 0x80, 0x00}}, + {int32(2147483647), []byte{0xd2, 0x7f, 0xff, 0xff, 0xff}}, + {int32(-2147483648), []byte{0xd2, 0x80, 0x00, 0x00, 0x00}}, + {int64(2147483648), []byte{0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}}, + {int64(-2147483649), []byte{0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff}}, + {int8(1), []byte{0xd0, 0x01}}, + {int16(1), []byte{0xd1, 0x00, 0x01}}, + {int32(1), []byte{0xd2, 0x00, 0x00, 0x00, 0x01}}, + {int64(1), []byte{0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + + // fixint (uint) + {uint(0), []byte{0}}, + {uint(2), []byte{2}}, + + // uint + {uint(255), []byte{0xcc, 0xff}}, + {uint(256), []byte{0xcd, 0x01, 0x00}}, + {uint(65536), []byte{0xce, 0x00, 0x01, 0x00, 0x00}}, + {uint(4294967296), []byte{0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}}, + + // sized uint + {uint8(255), []byte{0xcc, 0xff}}, + {uint16(256), []byte{0xcd, 0x01, 0x00}}, + {uint32(65536), []byte{0xce, 0x00, 0x01, 0x00, 0x00}}, + {uint64(4294967296), []byte{0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}}, + {uint8(1), []byte{0xcc, 0x01}}, + {uint16(1), []byte{0xcd, 0x00, 0x01}}, + {uint32(1), []byte{0xce, 0x00, 0x00, 0x00, 0x01}}, + {uint64(1), []byte{0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + + // float + {float32(3.141592), []byte{0xca, 0x40, 0x49, 0x0f, 0xd8}}, + {float64(3.141592), []byte{0xcb, 0x40, 0x09, 0x21, 0xfa, 0xfc, 0x8b, 0x00, 0x7a}}, + + // String + makeStringCase("", []byte{0xa0}), + makeStringCase("Hello, World!", []byte{0xad}), + makeStringCase("Lorem ipsum dolor sit amet, consectetur porttitor.", []byte{0xd9, 0x32}), + makeStringCase(str16test, []byte{0xda, 0x77, 0xc7}), + makeStringCase(str32test, []byte{0xdb, 0x00, 0x01, 0x35, 0x05}), + + // Binary + makeBinaryCase([]byte{}, []byte{0xc4, 0x00}), + makeBinaryCase([]byte("Hello, World!"), []byte{0xc4, 0x0d}), + makeBinaryCase([]byte("Lorem ipsum dolor sit amet, consectetur porttitor."), []byte{0xc4, 0x32}), + makeBinaryCase([]byte(str16test), []byte{0xc5, 0x77, 0xc7}), + makeBinaryCase([]byte(str32test), []byte{0xc6, 0x00, 0x01, 0x35, 0x05}), + + // Array + {newTestArray(0), []byte{0x90}}, + {newTestArray(1), []byte{0x91, 0x01}}, + {newTestArray(2), []byte{0x92, 0x01, 0x01}}, + {newTestArray(16), append([]byte{0xdc, 0x00, 0x10}, bytes.Repeat([]byte{0x01}, 16)...)}, + {newTestArray(65536), append([]byte{0xdd, 0x00, 0x01, 0x00, 0x00}, bytes.Repeat([]byte{0x01}, 65536)...)}, + + // Map + makeMapCase(0, []byte{0x80}), + makeMapCase(1, []byte{0x81}), + makeMapCase(2, []byte{0x82}), + makeMapCase(16, []byte{0xde, 0x00, 0x10}), + makeMapCase(65536, []byte{0xdf, 0x00, 0x01, 0x00, 0x00}), + + // Extension + {&testExt{1}, []byte{0xd4, 0x01, '_'}}, + {&testExt{2}, []byte{0xd5, 0x01, '_', '_'}}, + {&testExt{4}, append([]byte{0xd6, 0x01}, bytes.Repeat([]byte{'_'}, 4)...)}, + {&testExt{8}, append([]byte{0xd7, 0x01}, bytes.Repeat([]byte{'_'}, 8)...)}, + {&testExt{16}, append([]byte{0xd8, 0x01}, bytes.Repeat([]byte{'_'}, 16)...)}, + {&testExt{3}, append([]byte{0xc7, 0x03, 0x01}, bytes.Repeat([]byte{'_'}, 3)...)}, + {&testExt{256}, append([]byte{0xc8, 0x01, 0x00, 0x01}, bytes.Repeat([]byte{'_'}, 256)...)}, + {&testExt{65536}, append([]byte{0xc9, 0x00, 0x01, 0x00, 0x00, 0x01}, bytes.Repeat([]byte{'_'}, 65536)...)}, + + // Timestamp + { + time.Date(1999, 3, 1, 0, 0, 0, 0, time.UTC), // 920246400 + []byte{0xd6, 0xff, 0x36, 0xd9, 0xd8, 0x80}, + }, + { + time.Date(2106, 2, 7, 6, 28, 16, 0, time.UTC), // 4294967296 + []byte{0xd7, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, + }, + { + time.Date(2021, 8, 12, 05, 57, 21, 536870912, time.UTC), // 1628747841.536870912 + []byte{0xd7, 0xff, 0x80, 0x00, 0x00, 0x00, 0x61, 0x14, 0xB8, 0x41}, + }, + { + time.Date(2514, 5, 30, 1, 53, 04, 536870912, time.UTC), // 17179869184.536870912 + []byte{0xc7, 0x0c, 0xff, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, + }, +} + +type testArray []int + +var _ Array = (*testArray)(nil) + +func newTestArray(n int) *testArray { + arr := make(testArray, n) + for i := range arr { + arr[i] = 1 + } + return &arr +} + +func (t *testArray) EncodeMsgpackArray(e *Encoder) { + for i := 0; i < len(*t); i++ { + e.Int(1) + } +} + +func (t *testArray) DecodeMsgpackArray(d *Decoder, n int) error { + *t = make(testArray, n) + var v int + for i := 0; i < n; i++ { + err := d.Int(&v) + if err != nil { + return err + } + (*t)[i] = v + } + return nil +} + +func (t *testArray) Len() int { + return len(*t) +} + +type testMap []int + +var _ Map = (*testMap)(nil) + +func newTestMap(n int) *testMap { + v := make(testMap, n) + for i := 0; i < n; i++ { + v[i] = 1 + } + return &v +} + +func (t *testMap) EncodeMsgpackMap(e *Encoder) { + for k, v := range *t { + e.Uint64(uint64(k)) + e.Int(v) + } +} + +func (t *testMap) DecodeMsgpackMap(d *Decoder, n int) error { + *t = make(testMap, n) + + var ( + key uint64 + val int + err error + ) + + for i := 0; i < n; i++ { + err = d.Uint64(&key) + if err != nil { + return err + } + + err = d.Int(&val) + if err != nil { + return err + } + + (*t)[key] = val + } + + return nil +} + +func (t *testMap) Size() int { + return len(*t) +} + +type testExt struct { + n int +} + +var _ Extension = (*testExt)(nil) + +func (t *testExt) EncodeMsgpackExt(e *Encoder) { + e.Raw(bytes.Repeat([]byte{'_'}, t.n)) +} + +func (t *testExt) DecodeMsgpackExt(d *Decoder, typ int8, size int) error { + if typ != t.Type() { + return fmt.Errorf("ext/decode: expected type was %d, got: %d", t.Type(), typ) + } + t.n = size + + buf := make([]byte, t.n) + err := d.Raw(buf) + if err != nil { + return err + } + if !bytes.Equal(buf, bytes.Repeat([]byte{'_'}, t.n)) { + return fmt.Errorf("ext/decode: expected value was []byte{'_' * %d}, got: %v", t.n, buf) + } + return nil +} + +func (t *testExt) Type() int8 { + return 1 +} + +func (t *testExt) Size() int { + return t.n +} diff --git a/str16_test.txt b/str16_test.txt @@ -0,0 +1,99 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sem felis, lacinia et egestas et, accumsan vitae nisi. Ut id scelerisque purus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis consequat aliquet turpis. Integer vitae turpis placerat, vestibulum nisi sed, varius nulla. Cras tellus mi, scelerisque ac venenatis eu, blandit vitae mi. Donec laoreet aliquet venenatis. Donec ut sem a turpis tincidunt accumsan. Aenean non libero ac massa imperdiet luctus quis sit amet diam. + +Donec lorem turpis, commodo quis velit eu, vestibulum gravida mi. Sed vitae porta enim. Praesent at turpis enim. Etiam feugiat risus nec elit cursus, at vehicula purus volutpat. Donec metus eros, scelerisque vel metus congue, sollicitudin venenatis purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis iaculis mattis fringilla. Pellentesque id purus feugiat, semper lorem at, interdum neque. + +Curabitur nec magna eu lacus tempus posuere sed quis enim. Sed at felis semper, tincidunt diam at, sollicitudin libero. Proin vitae dui efficitur, ultricies augue ornare, fermentum nulla. Donec dapibus ultrices mi, vel rutrum arcu molestie ac. Donec convallis et sapien non dignissim. Suspendisse potenti. Donec ac leo id lectus aliquam condimentum. Nam eu aliquam lectus. + +Curabitur posuere felis sed odio lacinia, vitae eleifend felis ornare. Donec malesuada, augue non commodo egestas, libero nulla laoreet massa, ac facilisis enim massa a nulla. Integer ultricies luctus imperdiet. Nunc ut accumsan purus, eget laoreet enim. Proin in nulla sollicitudin, volutpat orci vel, pretium purus. Vivamus luctus cursus orci vel eleifend. Proin vitae lectus eget mi feugiat ultricies. Vivamus consequat lorem ac dui venenatis vulputate. Nunc bibendum accumsan sapien ut congue. Pellentesque venenatis dictum ligula, vel lacinia dolor placerat ut. Aliquam elementum convallis justo. Proin laoreet nunc at posuere convallis. Sed velit nulla, bibendum eget suscipit id, dapibus consequat eros. + +Praesent porta lectus eu quam dapibus auctor. Vivamus viverra et nunc ac tincidunt. Nulla ultrices massa eros, a pretium turpis tincidunt sit amet. Nunc sodales urna sit amet arcu tincidunt molestie. Aenean scelerisque interdum leo, sed pulvinar nulla commodo ac. In tellus mi, consequat at fermentum et, pulvinar vitae augue. In cursus eget elit et elementum. Vivamus maximus vestibulum justo, a elementum massa pretium ac. Donec nec pellentesque sem, ac tempor ex. Quisque gravida ante quis elementum placerat. Duis semper ligula ac interdum semper. Suspendisse potenti. Vestibulum justo purus, ullamcorper in commodo consequat, molestie accumsan quam. Donec vel magna mi. Maecenas quis ultricies velit. + +Etiam dapibus mauris quis metus ultricies ultrices. Curabitur feugiat justo ac sem volutpat, vel sagittis massa porta. Phasellus mattis posuere justo a tempor. In eleifend enim vel luctus suscipit. Quisque ullamcorper condimentum ultricies. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur gravida semper diam, a porttitor magna facilisis id. Quisque elementum erat at purus congue, nec mollis turpis dictum. Curabitur placerat lobortis ipsum nec suscipit. Quisque odio dui, egestas eu bibendum nec, aliquet sed tellus. Ut nisl velit, blandit in tellus id, ultricies condimentum nunc. Nullam leo lorem, sollicitudin vel nulla quis, varius blandit dui. Morbi ac felis tortor. Curabitur porta, est sit amet iaculis accumsan, augue purus viverra mi, vitae consequat quam felis et ante. Integer accumsan venenatis metus, ut condimentum elit. + +Pellentesque commodo tristique erat. Nunc mattis, magna vel maximus tristique, arcu lorem consectetur dolor, ac ullamcorper erat justo non nisl. Donec porta turpis ut mattis maximus. Duis efficitur posuere molestie. Morbi lacinia accumsan enim, laoreet placerat urna feugiat ut. Fusce sed venenatis nunc. Proin sed porttitor augue, ac pulvinar elit. Curabitur neque enim, volutpat vitae fringilla vel, vestibulum id ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin dignissim mauris ut vulputate blandit. Quisque viverra lacinia neque, sollicitudin porta mauris vulputate euismod. Cras pulvinar viverra lectus ac imperdiet. Fusce egestas venenatis dignissim. Pellentesque fermentum, orci ut molestie cursus, ipsum ligula imperdiet massa, sed faucibus arcu nunc vitae justo. + +Quisque nec sapien egestas, sagittis tortor sit amet, pretium quam. Nulla aliquet, velit a imperdiet facilisis, tortor arcu rutrum metus, in malesuada mi mauris non velit. In sollicitudin turpis non cursus scelerisque. Phasellus at tortor vulputate, hendrerit enim nec, tincidunt lorem. Pellentesque scelerisque blandit est ut pellentesque. Pellentesque sit amet risus tellus. Donec sit amet tincidunt eros. Fusce non nibh nec nulla mattis volutpat in sed est. Nunc dolor enim, tincidunt fringilla lobortis nec, facilisis quis metus. Morbi at justo pretium, fermentum tellus nec, facilisis ex. Fusce eu accumsan dolor. In luctus est sit amet ipsum vulputate fermentum. Fusce auctor volutpat commodo. Duis ac metus sagittis nisi porttitor vulputate. + +Sed vel rhoncus arcu. In posuere justo ut quam sollicitudin, id porta nibh maximus. Nulla bibendum ut justo ut sollicitudin. Sed turpis leo, sollicitudin eget nisi nec, suscipit lobortis lacus. Vestibulum odio purus, ornare iaculis finibus vel, rutrum at neque. Integer non enim at ex volutpat feugiat eu a velit. Sed hendrerit magna ut orci tristique ultrices. Aliquam sollicitudin posuere vestibulum. Aliquam at arcu in lectus finibus interdum. Integer non dolor sollicitudin, convallis orci et, feugiat lacus. + +Nunc vitae varius ligula. Maecenas nec augue a libero vulputate pellentesque et eget arcu. Suspendisse ut sollicitudin metus. Aenean ligula justo, scelerisque ornare lorem ut, aliquam pellentesque dui. Ut lobortis ut magna sed porta. Morbi imperdiet metus sit amet orci imperdiet iaculis. Etiam pharetra dui risus, in efficitur justo pellentesque sit amet. Cras at diam dolor. Nulla venenatis facilisis placerat. Nullam sem urna, vehicula a rutrum gravida, malesuada in risus. Cras ut nulla non neque dictum scelerisque non id justo. Duis convallis eu nibh a efficitur. Nullam lacus quam, dapibus quis varius ac, ultrices at eros. + +Pellentesque lacinia urna ac dolor venenatis, ut cursus sem venenatis. Fusce ornare tincidunt libero, condimentum euismod nulla aliquam eget. Ut et ullamcorper elit. In hac habitasse platea dictumst. Sed a lectus vel justo maximus cursus malesuada at lorem. Proin magna elit, finibus quis est quis, rutrum condimentum mauris. Duis metus nibh, rhoncus vel ex vitae, iaculis rutrum diam. Integer porttitor justo sed est molestie hendrerit. Nullam sed purus ac mauris suscipit auctor a vel augue. Donec consectetur nisi ac finibus venenatis. + +Vivamus neque ante, sollicitudin a lacinia eget, rhoncus eget mi. Cras rutrum augue id nisi iaculis vehicula. Sed orci tortor, congue vel diam at, condimentum condimentum dolor. Donec egestas convallis tortor, vel sodales arcu eleifend non. Curabitur accumsan ex placerat, tincidunt mi ut, pellentesque turpis. Curabitur fringilla quam quis blandit scelerisque. Donec fermentum leo lacinia nisl posuere maximus. Integer sollicitudin lobortis est vel sodales. Cras varius vulputate sem at faucibus. Duis tellus tortor, egestas sit amet nibh et, euismod cursus justo. Nam eget purus id augue scelerisque laoreet id ac magna. Integer lectus lectus, fermentum in nisi vel, iaculis finibus felis. Sed lorem libero, tincidunt ut ex vitae, finibus gravida est. Donec interdum justo a blandit tempor. Donec scelerisque in est et scelerisque. Praesent lectus risus, auctor id nibh quis, fermentum feugiat lorem. + +Sed euismod ac ex nec rutrum. Nam non neque ut metus eleifend fermentum quis eu magna. Quisque sed orci vel ligula lacinia tempor sit amet quis tortor. Morbi mollis eget justo vitae maximus. Nam volutpat volutpat justo, ac suscipit risus laoreet eget. Duis pulvinar mi quam, at tincidunt sem accumsan sed. Cras eu augue convallis, luctus sapien sed, porttitor velit. Pellentesque vel semper nulla, quis ullamcorper nisl. Proin nibh ipsum, eleifend in ex quis, malesuada interdum velit. Pellentesque mollis augue in ipsum ullamcorper sagittis. Donec tristique metus nec turpis aliquet vulputate. + +Etiam fringilla urna in tincidunt accumsan. Ut magna nisl, lobortis semper odio in, sagittis gravida sem. Donec ac pretium magna. Nulla ex turpis, commodo interdum blandit eu, semper ut ex. Vivamus sagittis nisi et ornare luctus. In eu massa non libero finibus pretium. Aenean mattis purus at justo consequat efficitur. Mauris venenatis elit quis est rhoncus, a tempor nibh pulvinar. Duis vel sagittis felis. Morbi scelerisque et elit ac aliquam. Maecenas tempor, ipsum scelerisque aliquet egestas, nisi ex iaculis turpis, a efficitur mi libero id metus. + +Pellentesque tincidunt molestie convallis. Duis dictum egestas finibus. Maecenas in sem eget ipsum pretium porttitor interdum non arcu. Nunc viverra iaculis leo porta tincidunt. Sed accumsan malesuada elementum. Vestibulum at dolor massa. Etiam nec commodo tortor. Ut tempor nunc eu accumsan blandit. Nam feugiat turpis sed dui pretium luctus. Vivamus hendrerit mauris at arcu auctor, at tempus sem lacinia. Mauris sed semper justo. Phasellus ut facilisis nunc. Nunc porta elit lacus, in pretium magna fringilla sit amet. Praesent iaculis ligula eget leo tristique gravida. Maecenas congue, enim vel semper consectetur, lorem dolor faucibus ex, non finibus nisi nisl at turpis. Donec blandit dapibus sapien, sed elementum dolor viverra quis. + +Fusce sed ultrices ex, sit amet maximus metus. Curabitur eleifend leo sit amet lorem ornare pulvinar. Pellentesque eget metus vitae nunc mattis pellentesque vel vitae neque. Duis efficitur diam ligula, sed varius justo pellentesque sit amet. Etiam a lacus augue. Mauris commodo fermentum sapien sit amet tincidunt. Sed et risus sit amet lacus ultrices pharetra nec aliquet risus. Nunc lacus arcu, pretium ut est vitae, mattis laoreet justo. Vestibulum est tellus, aliquet vel mi et, commodo porta arcu. Cras varius suscipit mauris, non sodales sem aliquet nec. Vestibulum metus leo, ullamcorper ut ultrices sit amet, suscipit vel nibh. + +Quisque nec tortor et tellus fringilla gravida malesuada sit amet est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla non elit elementum dui interdum lobortis nec ac arcu. Duis in odio ut enim rhoncus fringilla. Phasellus sit amet volutpat mauris. Aenean vel aliquet ipsum, id rutrum justo. Fusce lacinia pharetra purus, ut tincidunt nisl vestibulum sit amet. + +Quisque semper ac libero quis efficitur. Curabitur dignissim neque eget neque vehicula dignissim. Quisque pharetra mattis massa, id laoreet nunc mattis sit amet. Nam blandit purus porta nulla ornare placerat. In tincidunt ante ex, vel fringilla mi blandit non. Sed id nisi tellus. Morbi ultrices at nisl eu mattis. Cras consectetur consectetur arcu vitae scelerisque. Curabitur gravida odio eget neque pretium ultrices. Curabitur faucibus orci ac velit tempus, quis pharetra turpis egestas. Mauris consequat a turpis sit amet fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Suspendisse potenti. Suspendisse ultrices, nulla vitae vulputate rhoncus, metus mi elementum elit, pretium tempor nisl purus sed enim. Ut aliquet gravida augue eget egestas. + +Morbi in placerat magna, vitae auctor urna. Praesent elementum porttitor lacus. Suspendisse non justo ante. Nullam tempor lobortis varius. Nulla cursus vestibulum tincidunt. Donec suscipit porta augue, a auctor ligula condimentum vel. Quisque ut tempus diam. Sed dictum suscipit nulla sed elementum. Nulla tincidunt lobortis risus, eget accumsan velit euismod molestie. In a orci massa. + +Phasellus sit amet scelerisque ipsum. Duis volutpat posuere ex vel tincidunt. Morbi luctus pharetra dolor tincidunt varius. Etiam pharetra aliquam tortor, sed molestie enim tincidunt ut. Cras luctus vulputate diam. Nullam posuere justo sed ultricies finibus. Morbi sagittis pulvinar tellus, nec pulvinar odio suscipit sed. Vestibulum nec justo venenatis, lacinia quam eu, sollicitudin justo. Sed ac odio vulputate, blandit nunc eget, ornare tortor. Nulla eu dapibus mauris. Vivamus varius magna nec purus consectetur iaculis. Aliquam condimentum at ipsum vel pellentesque. Nam vitae lectus tempus, consectetur urna non, sodales arcu. + +Suspendisse sed pulvinar elit, nec luctus sem. Donec ac dolor imperdiet, bibendum mauris eget, eleifend velit. Donec eu dignissim turpis. Integer mi urna, interdum id tempor in, elementum sed lacus. Morbi ante quam, porttitor vitae congue laoreet, lacinia ornare dui. Sed nulla enim, tincidunt nec interdum nec, mollis eu nisi. Donec sit amet nisi viverra ipsum pretium egestas. Nullam aliquam est mattis, pulvinar lorem in, rhoncus libero. Morbi malesuada risus quis lacus auctor, eu feugiat augue maximus. Nunc ultricies efficitur diam. + +Nullam eget nunc ultrices, hendrerit sapien eu, sagittis ligula. Cras sed dolor fermentum, congue mauris venenatis, efficitur enim. Ut eget neque elit. Praesent et dui eu quam ultrices ultrices ac sit amet lacus. Fusce sollicitudin, ipsum sit amet feugiat rhoncus, tellus erat vestibulum purus, sit amet sodales dolor metus ac magna. Donec a pulvinar leo. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. + +Sed ac justo sit amet nibh vulputate hendrerit. Proin at ipsum libero. Nullam fermentum sit amet dui id accumsan. Nulla nec bibendum neque, sit amet aliquam neque. Donec nec risus vel lorem luctus maximus et a turpis. Praesent massa nulla, rutrum quis mattis eu, venenatis vestibulum mauris. Integer pharetra urna sit amet urna volutpat pellentesque. Ut semper leo eu metus tempus, ac accumsan arcu vestibulum. Integer ut eros quis arcu auctor hendrerit nec sollicitudin magna. Cras sem nisi, ullamcorper maximus lectus placerat, elementum iaculis tellus. + +Duis et luctus leo. Integer commodo erat ut viverra tincidunt. Nulla facilisi. Etiam non volutpat nulla. Morbi a nisi sagittis, aliquet est id, scelerisque lorem. Nulla facilisi. Maecenas nec leo neque. Sed lacinia lorem blandit, porta nulla tempor, feugiat dolor. Quisque vel commodo dolor. Fusce vulputate enim in iaculis mollis. + +Ut tempor vel magna placerat laoreet. Nulla ornare, ante a pellentesque venenatis, lacus tellus vestibulum quam, vel tincidunt libero mi a odio. Suspendisse sem magna, viverra ac consectetur et, mollis sed sem. Curabitur nec lectus eros. Pellentesque nec dui vestibulum, mattis velit non, dictum nisl. Sed convallis diam eget urna cursus fermentum. Maecenas vel lorem quis justo sodales efficitur. Proin dictum dolor sed diam elementum, eget dictum mauris laoreet. In ac dui vitae magna pulvinar dignissim vitae vitae risus. Pellentesque hendrerit quam non semper congue. Suspendisse potenti. Fusce sed blandit ipsum, id luctus lectus. Donec lectus est, viverra at ex at, luctus consequat ligula. Mauris lacus est, cursus et purus vitae, lobortis dignissim leo. Nullam et eleifend leo, eu suscipit mi. Suspendisse est tortor, aliquet vel orci id, efficitur volutpat orci. + +Donec commodo dui vel quam scelerisque aliquam. Nam molestie massa vitae ligula viverra, a consectetur nunc scelerisque. Aenean pharetra nisl justo, pretium elementum odio sagittis eget. Nulla eget imperdiet augue, nec condimentum libero. Fusce bibendum urna ut facilisis vestibulum. Duis varius, nisi gravida faucibus suscipit, eros massa gravida augue, non iaculis dolor felis id mi. Sed eget tempor nisi, non hendrerit sapien. Vestibulum diam felis, pretium eu arcu id, tristique aliquam quam. Duis sodales mi vestibulum vehicula lacinia. In venenatis tortor a erat molestie convallis. Nulla porttitor nec odio nec scelerisque. + +In pretium sodales orci ac hendrerit. Praesent at diam odio. Donec neque dui, venenatis a elit nec, dapibus mattis nisi. Sed ornare tellus eu aliquam tristique. Donec fringilla arcu ac tempus commodo. Maecenas ligula quam, ornare et bibendum eu, varius in nunc. Donec ante leo, tincidunt sed est porttitor, cursus semper tellus. + +Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In nec orci fermentum, imperdiet erat sed, porttitor lectus. Cras id elit venenatis, auctor tellus et, tristique augue. Etiam sodales malesuada lorem non mattis. Mauris sodales imperdiet gravida. Aliquam erat volutpat. Nam non tellus sit amet augue sollicitudin ultricies mattis a purus. Aenean aliquam volutpat enim, sit amet ullamcorper magna euismod nec. In lectus ex, viverra sit amet tortor semper, euismod feugiat libero. Phasellus tempor arcu neque, quis rutrum urna varius et. Vestibulum sit amet odio lacinia, mollis neque non, aliquam mi. Sed ultricies rhoncus ex, at ultrices tellus accumsan commodo. Integer et purus egestas, dapibus purus et, accumsan tellus. + +Donec laoreet ex at dolor aliquam faucibus. Vestibulum lacus enim, pretium a aliquet vitae, blandit quis libero. Quisque aliquet, nunc ut mollis faucibus, massa diam dapibus neque, quis placerat nibh risus in mauris. Duis a tortor ornare, finibus arcu in, sollicitudin velit. Nunc ut tortor in mi convallis condimentum vel a ante. Nulla facilisi. Quisque vitae consequat nisl. Pellentesque nisl lectus, pellentesque vitae risus sit amet, lobortis vulputate nisl. Nam in faucibus nisl, scelerisque luctus quam. Curabitur volutpat dictum nisl, auctor aliquet metus varius vel. Cras at magna sed dui euismod accumsan in non nunc. Aliquam et consectetur arcu. + +Aenean eu sapien arcu. Sed id elit eu tellus porta blandit. Curabitur eu mauris elementum, porta turpis vitae, pretium velit. Aliquam ullamcorper, neque vel pellentesque sollicitudin, magna ex scelerisque est, quis ullamcorper libero lectus consequat nunc. Etiam eleifend malesuada ante, vitae tincidunt libero consectetur quis. Quisque id sollicitudin nulla. Cras non nisl a leo fringilla placerat vitae non nisi. Pellentesque vitae iaculis justo, in pellentesque nulla. Quisque in malesuada nibh. In hendrerit nulla dictum, convallis orci maximus, aliquet mauris. Maecenas pretium, sem vitae volutpat dapibus, diam ante rutrum est, malesuada condimentum lacus velit interdum augue. Quisque pulvinar varius nisl eget bibendum. Vivamus gravida posuere ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Sed congue porta massa, quis bibendum orci rutrum sed. Nullam ac arcu arcu. Suspendisse tincidunt lorem tellus, sit amet bibendum justo euismod vehicula. Duis semper elit et dignissim gravida. Praesent ullamcorper eu est ut porttitor. Cras sit amet enim ut eros pulvinar condimentum sit amet nec nulla. Vestibulum blandit eget ex ut dictum. Suspendisse tempus ullamcorper neque in condimentum. Phasellus in convallis sapien. + +Mauris ac justo et mi mollis mattis non nec mauris. Phasellus sit amet faucibus purus. Proin sed orci scelerisque neque finibus dapibus lobortis et lacus. Cras nec feugiat lorem. Suspendisse a dapibus ante. Suspendisse aliquet urna sem, sit amet pellentesque sem lobortis vel. Aenean at nisl nec libero iaculis semper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed eget nisi faucibus, elementum turpis sed, convallis leo. Quisque eget dolor aliquet, facilisis purus at, pellentesque tortor. Nulla neque quam, porttitor eget ultrices a, dignissim vel magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque quis maximus tortor. Duis pellentesque dolor a lectus scelerisque, sed ultrices ipsum efficitur. Morbi pharetra odio nec magna porta semper. + +Aenean interdum massa tincidunt scelerisque dignissim. Quisque consequat viverra efficitur. Vestibulum id interdum purus. Donec mollis luctus pulvinar. Donec commodo arcu vitae leo volutpat pellentesque ac vel lectus. Etiam hendrerit varius pretium. Praesent enim turpis, gravida nec metus a, porttitor venenatis ex. Ut luctus velit quis vehicula venenatis. Proin posuere imperdiet rhoncus. Nam suscipit diam a purus rhoncus, vel commodo risus rutrum. Cras odio arcu, faucibus vel luctus vitae, condimentum ac enim. Vivamus sed massa at eros aliquam luctus. Nam mattis ipsum at nisi dictum viverra. Fusce dignissim justo id odio suscipit suscipit. + +Nam bibendum turpis vel mi porttitor hendrerit. In ut diam enim. Fusce quis gravida velit. Suspendisse neque ex, tempus eget lorem eget, consectetur aliquet libero. Praesent vehicula lorem eget velit sollicitudin, ut volutpat orci dictum. In hac habitasse platea dictumst. Ut mauris dolor, maximus at fringilla luctus, mattis nec velit. Ut ut diam turpis. Pellentesque imperdiet, tortor vitae tincidunt fringilla, purus justo fermentum magna, ac scelerisque quam urna mattis nunc. Mauris auctor augue ac elit gravida tincidunt. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur commodo leo interdum massa venenatis gravida. Donec consequat dolor et odio volutpat, sed pulvinar sapien fermentum. Vivamus rhoncus vehicula hendrerit. + +Nunc hendrerit efficitur nulla, non dictum nulla imperdiet eu. Praesent accumsan lacus tempus, tristique nulla eget, porttitor risus. Etiam imperdiet ligula nibh, eget tempus neque blandit ut. Aliquam turpis lectus, aliquam non purus sed, facilisis vehicula quam. Duis dictum tristique enim, ut facilisis felis iaculis commodo. Aliquam erat volutpat. Sed a nibh faucibus elit egestas blandit non non nulla. + +Cras cursus lectus ac imperdiet rutrum. Praesent iaculis et odio quis convallis. Ut vel iaculis tortor, ac vestibulum nisi. Sed congue sit amet diam vitae feugiat. Vivamus hendrerit purus eget dictum fringilla. Duis tincidunt ligula ut finibus commodo. Nulla a convallis massa, in feugiat orci. + +Proin vestibulum euismod libero, et dapibus felis consequat non. Vestibulum dapibus ex tellus, id aliquam urna gravida non. Mauris sit amet purus erat. Ut scelerisque libero at sapien sodales, sit amet viverra turpis interdum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nullam est tortor, dignissim non semper non, dignissim in nunc. Aliquam congue neque eget lectus porttitor, ut semper diam congue. Nam rutrum sollicitudin vulputate. Phasellus fermentum lectus non nisl pellentesque pharetra. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin vulputate odio purus, at pulvinar felis vestibulum accumsan. Donec sagittis quis risus eu commodo. + +Donec sapien neque, vulputate eget ligula eu, efficitur vehicula velit. In nec tortor id sem euismod pulvinar. Aenean vitae laoreet augue. Aenean elementum dolor nibh, quis venenatis mauris feugiat eu. Pellentesque eget tincidunt eros. Vivamus id nunc accumsan, vestibulum dui non, pretium justo. Nunc justo mi, convallis nec enim sed, volutpat sagittis arcu. Aenean pulvinar magna et nulla molestie tincidunt. Vivamus faucibus accumsan hendrerit. + +Morbi sit amet leo at ex posuere eleifend. Cras convallis metus lacus, dictum vulputate ipsum cursus eu. Donec facilisis mollis nisi, malesuada posuere sapien pulvinar ut. Nullam tempor fermentum erat et consequat. Integer volutpat suscipit sapien, nec egestas felis condimentum quis. Vivamus dapibus, eros ac viverra dictum, ante lectus egestas odio, ac ullamcorper tortor lacus vitae justo. Nulla ullamcorper lacus sollicitudin orci iaculis suscipit. In posuere maximus augue, sit amet semper nunc mollis eget. Aenean augue orci, pellentesque eu risus ac, maximus ornare enim. Donec condimentum lacus et pellentesque dapibus. Fusce consectetur libero arcu, sodales porta ex tincidunt eget. Phasellus lacinia in orci at pretium. + +Maecenas sodales quis dui eu tristique. Suspendisse porttitor aliquam placerat. Aliquam mattis eleifend nunc, quis sodales est fringilla at. Morbi dignissim quam lectus, id consectetur augue fermentum et. Donec malesuada massa vitae justo rhoncus, vitae mollis dolor ultrices. Praesent quam nisl, hendrerit in efficitur id, commodo et sapien. Morbi nec facilisis ex, quis feugiat massa. Donec blandit neque eget ex scelerisque laoreet. Vestibulum accumsan ante non nibh maximus placerat. Etiam imperdiet a neque vel rutrum. Quisque malesuada venenatis nibh, vitae tincidunt ex lobortis non. Duis nisl nibh, cursus et cursus eget, tempor a risus. Pellentesque sollicitudin eleifend risus, ut pellentesque sapien tempor nec. + +Nunc faucibus, lectus a tincidunt ullamcorper, lectus augue aliquet arcu, ut bibendum massa lacus vitae ex. Etiam ac gravida lectus. Donec scelerisque ullamcorper nisi, eu laoreet magna pulvinar sed. Suspendisse luctus ipsum non felis lobortis iaculis. Curabitur mollis euismod nisi accumsan varius. In hac habitasse platea dictumst. Mauris pellentesque ultrices velit. + +Donec facilisis purus nunc, sit amet bibendum neque lacinia nec. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Maecenas malesuada in diam ut rutrum. Praesent placerat sit amet orci at vestibulum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce scelerisque tempus mi in bibendum. Morbi et vulputate elit. Sed porta ut lectus faucibus ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Phasellus sem sem, faucibus in sagittis nec, consectetur quis risus. Nullam a ex urna. Aliquam scelerisque lorem odio, sit amet blandit sem cursus at. Proin commodo ultricies porta. Vestibulum nec convallis ipsum, sit amet tempor est. Duis vitae semper dui. + +Ut consequat ultrices convallis. In venenatis erat in risus placerat, eget gravida ligula mattis. Aliquam fermentum aliquam ipsum ac porta. Vivamus a consequat turpis, aliquet volutpat ipsum. Nunc nec gravida ipsum. Vivamus malesuada malesuada felis, sed consequat nulla porttitor ac. Ut sit amet varius ligula, ac placerat magna. Proin consectetur ornare sem in rutrum. Integer quis accumsan turpis, vitae viverra ligula. Pellentesque interdum imperdiet est. + +Phasellus auctor congue ultrices. Quisque commodo a nulla sed volutpat. Ut eleifend mi sed condimentum porttitor. Donec vestibulum leo ac risus pellentesque ornare. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean posuere est at ligula euismod, eget malesuada elit rutrum. Cras dignissim sagittis metus eu pulvinar. Donec vitae sodales elit. Maecenas lacinia turpis dui, ut accumsan tortor ornare sit amet. Quisque eget magna ultricies, vestibulum justo sed, rutrum urna. Sed commodo fermentum placerat. Proin nisi tellus, consequat a aliquet ut, congue eget tellus. Fusce porta mollis nisi, non maximus mauris vestibulum ac. Sed mi neque, finibus a sollicitudin eu, dictum sed arcu. + +Morbi sit amet egestas metus. Integer pellentesque sollicitudin tincidunt. Maecenas et tortor bibendum, dapibus risus ut, pretium quam. Phasellus dignissim dignissim mattis. Sed malesuada ipsum vel aliquet porttitor. Ut viverra elit mauris, vel condimentum purus gravida ac. Etiam ultricies vel sapien ac commodo. Nullam sollicitudin, mi ut euismod vehicula, libero nisi ultrices tortor, eget ultricies mi purus at dui. Ut ligula lorem, efficitur sit amet iaculis vel, pellentesque ac libero. Phasellus posuere nisi vel felis consectetur, id cursus massa euismod. + +Nunc mattis mi a metus ultricies, vel faucibus magna dapibus. Nunc vitae rhoncus elit, et varius urna. Proin placerat iaculis quam, vitae luctus est vehicula ac. Suspendisse efficitur vitae nunc ut commodo. Sed volutpat nisi quis urna molestie condimentum. Etiam dapibus ipsum feugiat interdum ullamcorper. Vestibulum cursus aliquam nisi, a sollicitudin mauris suscipit sed. Proin vestibulum sem sed nunc vehicula, ut interdum velit dapibus. Cras ac pharetra lectus. Fusce erat erat, auctor a lorem sollicitudin, pulvinar luctus leo. Proin purus nisl, vulputate at sollicitudin vitae, finibus sit amet ipsum. + +Maecenas fringilla dolor leo, id tempus neque porta id. Vestibulum at ante libero. Vivamus tempus ipsum luctus ante volutpat rutrum. Quisque porttitor sollicitudin est, ut congue erat viverra sed. Nullam auctor malesuada mi, vel vestibulum nisl lobortis vel. Etiam vestibulum, tellus a interdum sodales, enim elit ultrices diam, ut lobortis neque velit et mauris. Pellentesque dapibus imperdiet pellentesque. Nulla porta finibus nunc. Donec quis justo erat. Quisque vel eleifend ex, id auctor massa. Sed porta finibus elementum. Pellentesque sodales nunc eget enim fermentum, nec bibendum nulla congue. Etiam consectetur sit amet arcu non aliquet. + +Sed viverra sem nec pulvinar tincidunt. Phasellus euismod fermentum auctor. Suspendisse congue ligula eget pretium hendrerit. Ut eleifend est arcu, id aliquet sapien gravida vitae. Sed dictum urna sed lobortis semper. Integer quis eros eu ex egestas bibendum sed nec elit. Quisque id dignissim ligula. Phasellus molestie fermentum vulputate. Vestibulum a molestie nunc, rhoncus mattis sapien. Duis vitae fermentum risus. Duis ac vehicula urna. Pellentesque aliquet orci eu augue viverra, eget porta massa elementum. Proin mollis mi commodo nisi pellentesque, nec vulputate erat fringilla. Nunc pulvinar vehicula nulla, ac aliquet odio viverra eu. Maecenas mollis arcu eget convallis dictum. Nulla non convallis nibh, sed malesuada metus. + +Mauris eu libero lorem. Ut leo nulla, luctus in nibh ut, rhoncus auctor augue. Vestibulum aliquam vel dui vitae volutpat. Sed id urna quis metus efficitur pharetra. Vestibulum vitae nisl scelerisque, luctus magna sed, volutpat ligula. Nunc arcu ligula, feugiat non vestibulum vel, dictum et urna. Nulla suscipit ligula eget sodales aliquam. Donec lectus lacus, tristique a nunc sed, fringilla fermentum libero. Sed purus orci, accumsan vitae vestibulum quis, volutpat non tellus. Morbi a sem quam. Sed feugiat quam non tincidunt dictum. + +Mauris nec quam consequat, gravida ligula sit amet, porttitor nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras vel mauris ullamcorper, laoreet metus id, vehicula lectus. Integer scelerisque augue in iaculis tincidunt. Nunc consectetur lacus non ex condimentum, et pretium turpis convallis. Fusce aliquam nulla risus, at fermentum enim fringilla ac. Nam purus elit, posuere eu maximus sit amet, porta eget ligula. Vivamus tristique leo eget nibh tempor accumsan. Donec suscipit elit nec tortor eleifend, quis vulputate sapien consequat. Etiam sagittis felis tortor, vitae feugiat enim consectetur ornare. Donec ac convallis ipsum. Morbi rhoncus lacus a faucibus egestas. diff --git a/str32_test.txt b/str32_test.txt @@ -0,0 +1,249 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultricies lacus erat. Cras accumsan porttitor pellentesque. Aenean rhoncus aliquet justo. Etiam non quam lorem. Nullam condimentum ex eget commodo finibus. Integer vitae tristique nisl. Etiam varius magna nisl, sit amet venenatis ipsum congue nec. In dictum eros ac lectus viverra fermentum nec at turpis. Nullam vitae blandit odio. Donec feugiat, nibh et tempus imperdiet, purus mauris vehicula purus, non vehicula velit ligula in eros. + +Nulla nec scelerisque libero. Curabitur tortor urna, sodales in euismod sit amet, consequat vel dolor. Donec ut lacus volutpat, sodales ipsum quis, pharetra velit. Quisque lobortis nisi non massa molestie, eu porta ante gravida. Morbi vel iaculis lectus. Integer non ex dolor. Pellentesque suscipit odio gravida sapien eleifend semper. Morbi fermentum vulputate est vel commodo. Nullam eu pretium eros, id imperdiet lacus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Fusce nibh nibh, aliquam at odio eu, facilisis sodales eros. Sed nunc sapien, posuere quis scelerisque eget, viverra nec magna. Proin facilisis massa a metus dictum, et viverra libero ullamcorper. Integer vitae ipsum a ligula vehicula cursus sit amet id nisi. Nunc tempor est leo, vitae convallis dolor facilisis vitae. Fusce vel leo cursus, placerat urna malesuada, mattis leo. Quisque ultrices turpis ac cursus consectetur. Fusce odio felis, congue et massa ac, condimentum sodales nisl. Etiam sit amet enim velit. Curabitur ullamcorper augue a erat finibus, at ultricies diam interdum. + +Vestibulum fringilla porta nisl, at faucibus nisi volutpat vitae. Aenean eu quam in lorem volutpat ullamcorper nec ut libero. Aliquam erat volutpat. Nullam diam nulla, tincidunt ac nisl ut, placerat tristique mauris. Integer in quam eu diam dapibus mollis at et nisi. Cras mauris dui, euismod quis elit ac, ornare elementum sem. In quis posuere nulla. Pellentesque placerat commodo dui malesuada luctus. Sed non hendrerit est, quis tempor ligula. Pellentesque ullamcorper eleifend luctus. Proin euismod quam enim, aliquet scelerisque quam porttitor a. + +Nulla sem ex, condimentum gravida ultrices maximus, lacinia vel augue. Curabitur blandit nibh augue, id iaculis libero commodo non. Etiam vel est et justo ultrices vehicula. Proin gravida lacus libero, in vehicula mi molestie a. Vestibulum non ultricies risus, nec lobortis risus. Nullam varius tellus at ante fermentum, nec elementum lorem laoreet. Pellentesque rhoncus libero risus, ac maximus magna volutpat ac. Integer ac consequat mi. Cras ac tellus sollicitudin, aliquam ex sed, interdum dolor. Nunc non volutpat ante. Vivamus eget purus ex. Nullam id dictum est. Proin vel pellentesque libero. In pellentesque dolor sit amet dui ultrices malesuada. + +Sed eu sapien accumsan lorem aliquet lacinia. Proin iaculis volutpat odio, non auctor lacus mattis id. Praesent et risus vitae nisi rutrum vestibulum non sed libero. Sed gravida pharetra tempus. Aenean vestibulum mauris et faucibus fermentum. Aliquam libero sem, varius quis fringilla at, varius ut nunc. Fusce quis pulvinar odio, vel fringilla orci. Cras vel aliquam massa. Suspendisse blandit faucibus sapien, non faucibus ipsum viverra sed. Cras sollicitudin laoreet ullamcorper. Vivamus molestie sapien et justo aliquet auctor nec et ligula. Duis id dui tortor. Aliquam erat volutpat. Integer dictum, diam vel interdum pretium, justo erat eleifend ipsum, ac aliquam magna purus quis ante. Vivamus tincidunt nisl convallis, tristique libero eu, laoreet massa. + +Nam sodales, est id condimentum suscipit, mauris odio finibus justo, vitae scelerisque lacus metus eget eros. Phasellus et rhoncus diam, at mattis nulla. Nullam placerat nibh ex, eget facilisis dui aliquam ut. Aliquam faucibus vestibulum erat sed rhoncus. Nulla gravida, erat id fringilla elementum, eros justo accumsan mauris, nec vulputate est nibh eu massa. Etiam dictum tellus sit amet sodales accumsan. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc magna elit, porta scelerisque tellus et, rhoncus viverra felis. Vivamus vel blandit diam. Sed nec egestas dolor. Etiam lacinia lorem diam. Duis non ullamcorper neque. + +Sed faucibus enim id justo malesuada ornare. Duis ac urna volutpat, posuere libero consequat, sagittis tortor. Mauris congue velit eu lectus mollis, eu malesuada velit sodales. Ut pretium enim a neque congue, eget dignissim massa elementum. Donec laoreet vitae ipsum ac imperdiet. Donec dignissim, magna ut congue facilisis, ligula erat luctus dolor, non rhoncus nunc dolor id ipsum. Quisque sem erat, imperdiet ut laoreet et, blandit et odio. Morbi auctor, justo sit amet euismod dignissim, ante lacus condimentum orci, ut placerat metus nisi sit amet erat. Vivamus non neque leo. Cras sit amet cursus augue, at porttitor massa. Cras vel nibh vitae felis rutrum bibendum. Duis egestas finibus nisl in semper. Praesent sed auctor augue, sit amet fermentum massa. Donec fringilla ex ut orci feugiat sodales. Donec id nulla non enim placerat tincidunt et dictum sapien. Praesent rhoncus lorem ligula, in accumsan urna semper at. + +Suspendisse ac libero posuere, sagittis nisi nec, volutpat metus. Integer imperdiet luctus malesuada. Vivamus eget orci sit amet ipsum lobortis fermentum non id mi. Maecenas in molestie nisi, et vulputate augue. Donec quis blandit nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed sapien tellus, iaculis ac accumsan nec, lacinia et massa. Quisque a malesuada orci. Mauris eu pretium leo, sit amet dapibus sapien. Integer egestas elit non est finibus, elementum varius nibh tristique. Aliquam sit amet metus sed nunc feugiat ultricies. Praesent ligula nulla, faucibus vel arcu quis, porta pretium massa. + +Donec sed tortor scelerisque, dignissim est at, volutpat purus. Integer at enim eget lorem tempus facilisis eu id enim. Donec ac vehicula ante, eu rhoncus augue. Ut est massa, commodo ut urna nec, efficitur pharetra nisi. Nulla eget neque turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Mauris et semper risus. In convallis pellentesque metus. Donec ut facilisis tellus, gravida aliquam lorem. Vestibulum feugiat lectus et nisl laoreet ultrices. Cras vulputate volutpat ligula, in mollis ex venenatis vel. Aenean ornare ligula felis, vel fringilla quam ultrices id. Proin non mollis lorem, ac rutrum urna. Suspendisse sed orci dui. Quisque scelerisque, nisi at tincidunt laoreet, risus ipsum iaculis nunc, eu elementum nunc massa a elit. + +Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam metus lacus, efficitur at ante sed, placerat scelerisque arcu. Sed aliquam ante nec arcu rutrum pretium. Cras luctus nibh eget metus vestibulum, vel fermentum diam cursus. Phasellus feugiat leo sed elit pulvinar cursus. Etiam nec consequat mi. Sed vestibulum lacus vulputate tellus consequat, eget aliquet metus euismod. Aenean vulputate dolor et lacus mattis vulputate. Suspendisse feugiat, lorem ut dignissim vestibulum, nisl metus consectetur sem, eget convallis quam tellus id lacus. Donec sollicitudin iaculis justo at ornare. Vestibulum eget quam at est dictum euismod. Maecenas placerat dolor suscipit, vulputate nisi vitae, congue augue. Pellentesque lobortis arcu quis dolor cursus, vel ullamcorper sem gravida. In sodales lacinia arcu at convallis. Suspendisse potenti. + +In suscipit pretium dapibus. Aliquam erat volutpat. Vestibulum sed erat porta, tincidunt metus non, tincidunt arcu. Nam vestibulum felis eget cursus pharetra. Suspendisse vel sapien nibh. Praesent laoreet, ipsum id vestibulum pulvinar, nisl lorem viverra ligula, in luctus risus enim non ligula. Nulla id metus ac nunc interdum commodo ut sodales dolor. Fusce diam urna, posuere dictum dignissim id, pharetra vitae lorem. Nulla eget metus gravida, laoreet nisl ornare, ullamcorper dui. In vel lacus ultricies, hendrerit elit quis, aliquet libero. Aliquam sollicitudin feugiat diam, eget porta turpis vulputate a. Duis malesuada ut tortor vitae lobortis. Aliquam ex tortor, facilisis non finibus tincidunt, luctus ac libero. Nunc at auctor urna. + +Nunc et sodales sem, in pharetra dolor. Donec volutpat sollicitudin risus, at aliquam elit feugiat fermentum. Aliquam erat volutpat. Duis sit amet varius turpis. Integer congue est leo. Cras a dui quis arcu euismod condimentum. Ut accumsan, leo nec scelerisque venenatis, risus ante egestas sem, sed cursus erat tortor vitae justo. Nunc et quam sed tellus varius gravida vel in velit. Nunc malesuada vestibulum libero, ut hendrerit tellus laoreet at. Aliquam erat volutpat. In egestas metus consequat, varius lorem non, imperdiet massa. Donec vulputate dolor in rhoncus pulvinar. Vestibulum fermentum, ex sed faucibus eleifend, risus lorem tempus ipsum, et rutrum nisl diam nec libero. Nunc a commodo urna. Aenean id lectus felis. + +Donec rhoncus dui id felis placerat, sed dignissim sapien pellentesque. Nam eget ante suscipit, lacinia lacus at, egestas ex. Etiam ultrices dui sed dapibus bibendum. Duis ornare tellus vitae lacus sollicitudin rutrum. Donec ut nisi non mi venenatis consequat ut ut quam. Morbi non viverra nisl. In faucibus, purus eu finibus venenatis, nulla lectus hendrerit ipsum, sed tristique elit enim quis lorem. Nullam vel eleifend magna, in accumsan nisl. Etiam rutrum enim eu enim euismod porta. + +Etiam et congue lectus, sed gravida nunc. Donec euismod congue sollicitudin. Proin consequat nulla id sollicitudin placerat. Pellentesque eget elit eget erat iaculis ultricies eu at massa. Proin sit amet nisi vel sapien volutpat condimentum. Duis tempor sem eu tortor auctor auctor. Maecenas turpis nisi, posuere sed aliquam in, iaculis in diam. Fusce ac lorem dui. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse sed pellentesque turpis. Sed diam libero, ultrices non felis id, pulvinar fringilla tellus. + +Aenean justo tellus, maximus a ornare nec, suscipit quis magna. Praesent sodales lacus vel ex auctor vestibulum. Proin vitae blandit quam. Aenean bibendum turpis porta turpis vestibulum, id scelerisque quam sollicitudin. Cras tincidunt justo felis, sit amet volutpat libero efficitur id. Vestibulum in ante sed orci scelerisque sodales sed sit amet enim. Maecenas interdum dui nec sem lobortis dictum. Cras placerat convallis dui, in rutrum est ultrices a. Aenean id elit ligula. Mauris laoreet suscipit libero, id congue nibh fermentum quis. Morbi pretium in ipsum quis porttitor. + +Ut posuere nisi neque, eu blandit nibh tincidunt eu. Curabitur vestibulum orci ut justo placerat interdum. Ut eu neque nec ligula lobortis vulputate. Donec ultricies fermentum urna ut faucibus. Aliquam dictum nibh odio, et condimentum lacus ultricies a. Fusce ultrices, leo sit amet suscipit convallis, lacus lacus imperdiet ligula, quis congue neque ipsum et magna. Sed sollicitudin porttitor est, eu viverra lorem volutpat eleifend. Sed ac eros semper, blandit tellus vulputate, sollicitudin purus. Fusce lobortis risus nec ligula tempus sollicitudin. Quisque rhoncus quam id dapibus malesuada. + +Etiam facilisis enim in mattis efficitur. Aliquam fermentum, libero sed dignissim faucibus, risus massa fringilla sapien, at ornare felis orci at risus. Vestibulum suscipit varius tortor a vestibulum. Cras pharetra lectus et dapibus molestie. Sed hendrerit rutrum nisi eu hendrerit. Duis sed nisl sit amet nulla fringilla blandit. Vestibulum vitae maximus mauris. In quis vulputate nisl, vestibulum mollis ante. Vestibulum ut nulla eget arcu molestie dictum vitae at massa. Proin tellus metus, interdum non eros et, pretium gravida mauris. Pellentesque viverra semper risus, vitae volutpat urna posuere tristique. Aliquam hendrerit sem lorem, eu scelerisque nulla consectetur a. + +Pellentesque congue arcu ut aliquam suscipit. Nullam eu dui quis risus consequat maximus. Etiam vehicula rhoncus nulla. Proin vestibulum maximus pharetra. In luctus massa at lorem finibus, et consequat nunc vulputate. Nulla euismod mauris diam, eget fermentum tortor feugiat varius. Nam tristique lacus lacinia purus feugiat pulvinar id ac quam. Pellentesque porttitor et neque sit amet ornare. + +Proin varius tincidunt gravida. Phasellus interdum justo at iaculis fermentum. Quisque sit amet risus vel eros iaculis tempor sed sed turpis. Phasellus in odio sit amet libero laoreet sollicitudin eu a enim. Vestibulum faucibus justo in porta ultrices. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec tristique, massa quis rutrum vehicula, eros quam euismod lacus, vitae convallis arcu sem vel tortor. Nam blandit lacus lectus, in porta eros sollicitudin id. Integer nec ipsum semper, egestas odio at, porta orci. + +Duis id consectetur mi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec blandit, elit ac lacinia accumsan, lorem lacus interdum lectus, eget molestie elit elit eget elit. Vivamus commodo commodo est id placerat. Mauris venenatis mi volutpat tortor ornare finibus. Proin ligula massa, vulputate eget pellentesque gravida, elementum congue orci. Sed condimentum massa a velit consectetur molestie. Ut sed convallis nunc. Nulla varius ante id ipsum convallis sagittis. Nullam sed nulla eget velit ornare consequat. Morbi tincidunt et est imperdiet varius. Mauris nulla quam, commodo ut odio et, finibus rhoncus massa. Curabitur purus nulla, malesuada quis lacus nec, hendrerit efficitur metus. + +Aenean nec blandit eros. Nam sed pellentesque ante, quis placerat eros. Aliquam eros tortor, mattis id porta ut, imperdiet sed mi. Donec volutpat tristique mi. Nam non scelerisque lacus, sit amet pulvinar risus. Pellentesque molestie tristique lectus, a tempor magna tempus id. Maecenas a vestibulum libero. Fusce lacus justo, pulvinar nec iaculis vitae, egestas vel odio. Integer viverra venenatis nisl, et maximus nulla iaculis sed. Sed porta diam a aliquam vehicula. Quisque mattis nunc ut pretium suscipit. Fusce tincidunt mauris quis mi convallis convallis. Integer ut nunc risus. Nulla elementum velit ut ante interdum, vestibulum congue magna tristique. + +Nam fermentum suscipit ligula, et luctus enim condimentum ut. Fusce vel sem et lacus consectetur vulputate. Phasellus luctus ipsum nec commodo tristique. Aliquam eget nulla ac urna tristique facilisis eget vel nunc. Phasellus in lectus et ipsum dictum accumsan. Proin ornare dolor nec ex tincidunt, non cursus ipsum tincidunt. In accumsan facilisis purus, tincidunt tempor felis euismod non. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus et ante leo. Etiam et vulputate arcu. Fusce vestibulum risus vitae risus ullamcorper, nec lobortis neque aliquet. Nunc ultrices pretium neque, et bibendum eros bibendum at. + +Duis purus augue, sollicitudin eu accumsan sit amet, condimentum sit amet purus. Praesent facilisis aliquet nisl. Phasellus feugiat rhoncus diam, sed venenatis libero sodales quis. Proin elementum, erat in ultricies elementum, diam risus laoreet erat, ut laoreet libero nunc vitae eros. Sed dictum ipsum est, id interdum sapien tincidunt eget. Donec vestibulum enim sit amet nisl ullamcorper commodo. Aliquam rutrum nisi id est tincidunt malesuada. Fusce sed metus odio. Morbi a diam nec tellus ultrices aliquet ut sit amet elit. Pellentesque commodo ipsum felis, quis tincidunt velit vehicula sit amet. Nulla imperdiet tincidunt mauris, eget semper elit vehicula non. Nulla eu pulvinar tellus. + +Ut sit amet justo id nibh tempus vulputate. Duis bibendum, erat in pharetra tempus, quam lorem pulvinar dolor, in scelerisque enim tellus a ipsum. Quisque cursus neque vitae erat efficitur, ut finibus nibh convallis. Curabitur turpis ipsum, porttitor ut ante ac, rhoncus pretium augue. Cras vel convallis ex. Mauris non lacinia enim, non viverra lorem. Sed felis quam, pellentesque et ex in, dictum lacinia nunc. Vivamus egestas, enim in facilisis fringilla, ipsum urna scelerisque mauris, eget mollis odio lectus vitae mauris. Fusce mi ligula, malesuada vel dui eu, scelerisque fermentum ante. Sed varius malesuada est, sed facilisis urna sodales ac. Cras luctus risus vel sapien fermentum bibendum. Quisque venenatis, ligula ullamcorper pulvinar maximus, odio nisl rutrum nibh, sed scelerisque tortor sem ullamcorper elit. Quisque in libero non ex mattis facilisis sed ut massa. Aliquam mauris lorem, lacinia id ullamcorper eget, facilisis sed ex. Vivamus luctus euismod odio, eget molestie libero tristique quis. + +Nulla facilisi. Nullam vehicula iaculis mauris et placerat. Phasellus volutpat cursus enim, eget tristique magna condimentum sed. In ut elit lectus. Vestibulum porttitor tincidunt est. Praesent suscipit scelerisque elit, vitae tincidunt nisi fermentum sed. Mauris at libero mauris. Praesent feugiat eleifend libero quis lobortis. Cras id pulvinar eros. Etiam fermentum, nisi id finibus molestie, est risus porta neque, ut scelerisque ligula neque nec mi. Quisque nibh eros, egestas sed eros non, commodo suscipit nulla. Donec condimentum mi eget dictum ultricies. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Ut elit nunc, luctus ac hendrerit eu, imperdiet et augue. Vestibulum quis vulputate felis, a varius est. Nam vel laoreet enim. Mauris finibus vehicula dolor, id lacinia velit egestas sit amet. Proin cursus, dui quis venenatis placerat, purus felis ultricies magna, et efficitur mauris augue sit amet augue. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque sollicitudin ipsum at lobortis aliquet. Sed at augue ac magna posuere vestibulum. Integer vehicula ex commodo, condimentum quam ac, finibus diam. Duis tincidunt quis ipsum eget mattis. Sed non venenatis mauris. Aliquam aliquam arcu efficitur arcu aliquet rutrum. Pellentesque in interdum libero. + +Cras eu viverra neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas libero eros, sagittis ac quam vitae, fringilla scelerisque nisi. Cras tristique lectus ac pulvinar rutrum. Proin at leo sed mauris mattis cursus. Duis eu feugiat metus. Vivamus volutpat nisi enim, vitae interdum odio egestas eget. + +Phasellus mattis erat tortor, at viverra lorem bibendum sit amet. Integer ac placerat nisi. Nulla eget accumsan mi. Sed iaculis velit dapibus, ultrices urna ac, placerat elit. Quisque consequat fringilla quam ac gravida. Aliquam condimentum tortor arcu, et suscipit orci ultrices a. Phasellus volutpat sapien eu lorem sodales vestibulum. Fusce sit amet risus ut nibh venenatis pharetra ac vel massa. Suspendisse elit magna, rutrum ut lectus et, egestas dapibus dui. + +Pellentesque eu eleifend quam, sit amet maximus nisi. Integer pharetra felis ornare ipsum condimentum fermentum. Cras aliquet tellus quis tincidunt rhoncus. Quisque ornare feugiat lorem et varius. Nullam ullamcorper neque condimentum, volutpat leo ut, vestibulum erat. Donec tempus tortor ut felis mattis, ac commodo purus aliquam. Phasellus ut felis non sapien gravida pellentesque. Morbi ac venenatis ex. Ut dignissim dapibus urna. Donec vitae laoreet sem. Donec porttitor lectus urna, a dignissim odio varius quis. Nam eu fringilla sem, eget auctor neque. Morbi nulla justo, hendrerit vitae ultricies et, consectetur eu erat. + +In eget erat quis velit posuere cursus. Morbi aliquam massa sit amet dolor maximus eleifend. Maecenas non porttitor quam. Praesent turpis nunc, sollicitudin sed est at, consectetur ultricies orci. Vestibulum risus metus, ultricies ac nunc sit amet, ullamcorper sagittis tellus. Integer finibus purus quis purus finibus, in porttitor nisl scelerisque. Pellentesque sit amet leo nibh. Cras cursus tortor et augue sodales luctus. Curabitur eu nunc ac tellus rhoncus tempus vel at nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque auctor cursus ipsum, vel cursus massa placerat eu. Vestibulum gravida nunc vel nulla imperdiet, quis pretium velit pretium. Ut sit amet gravida ligula. + +Vestibulum laoreet non nunc ac tempor. Praesent sed leo rhoncus, porta mauris nec, fermentum sapien. Nullam ut nulla nulla. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam auctor, tellus eu egestas ultrices, ex leo lobortis sem, in bibendum dui massa ut libero. Etiam venenatis ultrices leo, et iaculis nisl viverra non. Suspendisse efficitur aliquam ante, sed semper orci rhoncus non. Ut vitae nibh eros. Duis nec augue fringilla, euismod erat feugiat, eleifend ipsum. Nullam et interdum ligula. Fusce pretium urna vehicula leo placerat interdum. + +In non eleifend eros. Sed sed turpis a urna aliquam vestibulum. Sed eu odio pulvinar, tristique tortor vel, hendrerit justo. Aliquam non placerat diam. Duis fermentum tellus non fermentum sagittis. Sed iaculis tortor nec imperdiet consequat. Mauris in magna a eros iaculis tristique a vel ante. Ut vitae lorem sit amet odio dapibus ultricies sit amet in metus. Suspendisse quis est consequat, venenatis est vitae, maximus lacus. Suspendisse iaculis mi velit, non dignissim diam malesuada non. Nullam iaculis leo ut est venenatis tincidunt. Vivamus varius, libero at ultrices convallis, erat metus mattis erat, at egestas sem dolor a sapien. Praesent hendrerit, ipsum ac venenatis commodo, dolor mauris faucibus elit, sit amet vestibulum sem ipsum sed elit. Ut commodo ornare leo, non ullamcorper sapien. Morbi semper urna eget justo mattis rutrum. Nunc interdum aliquam placerat. + +Etiam et imperdiet turpis, et tempor neque. Aliquam id neque ex. Cras mauris felis, viverra at est sed, aliquam mattis quam. Sed fermentum fringilla urna sed pulvinar. Quisque ac sagittis mauris. Vivamus porta eget turpis vitae cursus. Vivamus euismod mattis nibh non pharetra. Morbi malesuada felis dui, pharetra tincidunt leo dictum sit amet. + +Maecenas non lacus aliquet, viverra urna sit amet, mollis nisl. Duis sit amet posuere ex. Phasellus ut mollis justo, non mattis mauris. Sed tempor nunc sit amet augue maximus, nec eleifend justo scelerisque. Vivamus malesuada porttitor faucibus. Donec vitae eros venenatis elit dignissim fringilla. Maecenas condimentum, purus ut gravida pellentesque, lectus sem placerat mauris, et lobortis quam mauris et velit. In dictum posuere velit ac viverra. Integer orci lacus, dictum a arcu sed, tincidunt gravida lacus. Proin fermentum blandit hendrerit. Nulla sed ornare nunc. In rhoncus nisi tincidunt lacus porttitor, laoreet congue ipsum maximus. Integer bibendum at urna vel ultricies. + +Nullam sit amet mauris faucibus, ultrices metus sed, dapibus nisi. Phasellus ut orci quis enim pulvinar fringilla vel nec massa. Aliquam erat volutpat. Aenean in auctor nulla, nec pellentesque arcu. Vivamus venenatis vitae tortor volutpat ultricies. Integer vitae interdum neque, sit amet iaculis est. Vivamus pellentesque quam vel purus vestibulum fringilla. Proin laoreet, sem feugiat rutrum mollis, sapien magna auctor ligula, a congue risus orci a sapien. Nullam non est ac est aliquam varius. Pellentesque molestie venenatis condimentum. Integer vel mauris erat. Quisque aliquet sem et lorem ultricies, et lacinia mauris tempor. Pellentesque at odio eu odio interdum suscipit. Fusce vitae quam sit amet purus sodales tristique at hendrerit mauris. Ut auctor convallis nibh dignissim eleifend. + +Integer eleifend eu justo vel commodo. Mauris sollicitudin finibus urna, eget mattis risus porttitor eu. Fusce posuere tellus in justo auctor, non fringilla arcu tempor. Donec laoreet enim magna, in bibendum risus porta ac. Ut condimentum arcu magna, nec congue felis sagittis id. Donec tortor sem, dapibus ut rutrum nec, varius auctor magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus iaculis id felis nec feugiat. Praesent mollis odio eget est efficitur ornare. Duis ac mi gravida, scelerisque diam ac, cursus purus. Curabitur et sem eget dolor volutpat commodo vel eget mauris. Vivamus id sem sit amet elit tempor posuere et nec massa. Etiam viverra purus id metus maximus fringilla. + +Donec a metus urna. Donec eget dolor odio. Nam vitae congue turpis. Quisque nec vehicula justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Praesent est nunc, ullamcorper eget lectus nec, semper cursus velit. Etiam eu rutrum ipsum, quis porta ex. Donec ante lorem, imperdiet et euismod sit amet, ornare sit amet orci. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus at turpis ac orci facilisis fringilla. Fusce pellentesque pretium sem sed ultrices. Quisque suscipit odio tortor, id ultrices metus blandit pulvinar. Sed tristique auctor efficitur. + +Aenean mi elit, rutrum ut iaculis eget, luctus a risus. Pellentesque laoreet consequat auctor. Proin semper, sapien quis aliquam iaculis, libero arcu porttitor ipsum, sed sollicitudin lectus dui et nibh. Vestibulum condimentum ex non pulvinar venenatis. Fusce tortor mi, lobortis non pulvinar sodales, fringilla a nisl. Nunc hendrerit magna nisi, in iaculis arcu eleifend at. Donec et ex pretium, accumsan felis ut, blandit turpis. Praesent eu lacus eget dui scelerisque pellentesque. Curabitur quis ipsum eget diam sodales scelerisque. Curabitur vitae cursus enim, in tempus nisl. Duis eget odio ut velit cursus pellentesque in eget nulla. Proin molestie metus et pellentesque auctor. + +Morbi at lacus sodales, porta neque a, blandit sem. Maecenas scelerisque risus varius lorem facilisis porta. Ut et venenatis lectus. Pellentesque pellentesque posuere leo quis rhoncus. Fusce vulputate, libero id tincidunt facilisis, tortor quam feugiat nisi, in vestibulum erat tellus nec leo. Sed ut velit nec sem vestibulum commodo vitae id metus. Vivamus aliquam finibus purus. Nullam iaculis porttitor ligula in tempus. Curabitur et posuere ipsum. Duis imperdiet nisl felis, et pellentesque lacus viverra sed. + +Morbi sed justo ex. Nam finibus vulputate lacus. Nunc congue mollis quam in finibus. Sed nibh erat, tristique sit amet lorem quis, mollis molestie neque. Donec euismod nibh ac finibus bibendum. Sed sed faucibus quam. In lorem quam, condimentum eget finibus dignissim, dapibus sit amet quam. Vestibulum vel lectus eu justo sollicitudin iaculis a at ante. Praesent commodo elementum velit sed mollis. + +Proin cursus nunc id porttitor lobortis. Morbi id dictum mauris. Praesent vestibulum accumsan facilisis. Phasellus fringilla ullamcorper tincidunt. Curabitur non mattis mi. Etiam ut luctus ipsum. Praesent tempus orci nunc, vitae interdum elit ullamcorper at. Nunc in leo tempor, dapibus felis sit amet, dignissim tortor. Morbi elit sapien, gravida vitae vestibulum id, tempor in erat. + +Integer venenatis erat at nulla lacinia hendrerit. Mauris dui metus, dapibus nec dui sed, condimentum laoreet tellus. Fusce auctor quis nibh ut tempus. Sed vulputate ut eros vitae feugiat. Etiam auctor lacus nec leo gravida, ut ornare sem convallis. Aliquam feugiat imperdiet luctus. Pellentesque suscipit luctus libero quis fringilla. Curabitur tempus aliquet ipsum, at dictum tortor vulputate in. Fusce iaculis volutpat magna id cursus. Proin euismod tortor in nibh accumsan dignissim. Nunc feugiat libero fringilla magna tempus, eu venenatis est sodales. Sed arcu ipsum, convallis in tortor vitae, aliquet faucibus mauris. Curabitur vel mollis libero. + +Morbi a dapibus mauris. Ut varius, mi quis fringilla accumsan, tortor odio commodo lacus, ut tincidunt nulla nisi eget dolor. Proin porttitor ipsum vitae dui fringilla, in ullamcorper massa varius. Pellentesque scelerisque ipsum non augue vestibulum, at vestibulum erat rhoncus. Vivamus eget magna enim. Cras posuere ipsum non diam dignissim, a ullamcorper nisi viverra. Vivamus suscipit ultricies enim sit amet tempus. Praesent ultricies orci euismod fermentum rhoncus. Curabitur porttitor augue sed magna fringilla, vel rutrum velit gravida. Fusce sagittis leo vel neque accumsan, vitae dictum elit maximus. Nunc dignissim dolor lobortis lorem tempus maximus. Sed fermentum elementum ipsum, posuere feugiat ipsum imperdiet vitae. Pellentesque malesuada arcu lectus, sit amet condimentum purus venenatis ac. Phasellus gravida quis felis et scelerisque. Nullam a justo pharetra, pellentesque diam sit amet, dignissim nulla. + +Donec accumsan elit et erat euismod, non pretium nisl iaculis. Proin magna nisl, imperdiet ut faucibus malesuada, molestie id enim. Ut molestie eros vitae justo tempus lacinia. Nulla convallis scelerisque luctus. Fusce in consequat turpis. In justo ex, imperdiet a fringilla pellentesque, aliquet et dui. Sed quis erat venenatis, mollis dui id, condimentum libero. Nullam ornare imperdiet nisl nec tristique. Nulla convallis libero risus, nec eleifend felis aliquet et. Curabitur orci libero, vulputate ut justo vel, blandit faucibus nunc. Vestibulum id sodales nisi. + +In hac habitasse platea dictumst. Phasellus purus lacus, pellentesque in sem sit amet, aliquam placerat erat. Mauris placerat leo ut ante pulvinar, id dignissim orci pretium. Nulla vitae purus ipsum. Aenean semper placerat ipsum, ut eleifend lacus pellentesque semper. Quisque vulputate sem in eros laoreet pretium. Nullam viverra tristique dictum. Curabitur sit amet viverra ex. Suspendisse sollicitudin tellus nibh, non bibendum sapien auctor sed. Nam pellentesque elit fermentum mi aliquam malesuada. Praesent finibus elit in consequat venenatis. Vivamus elementum est nisi, sit amet egestas felis pharetra a. Nullam consectetur, lectus at lobortis ultricies, justo felis molestie erat, eget fermentum libero purus eget mauris. Pellentesque vestibulum ac dolor id vehicula. Donec et ex sed velit tristique feugiat nec suscipit erat. + +Donec hendrerit risus augue, vel rutrum orci venenatis sit amet. Nunc facilisis gravida pharetra. Morbi aliquet arcu quis odio malesuada, blandit iaculis nunc convallis. Nulla porta purus pulvinar, molestie nisl ut, volutpat augue. Curabitur mollis ipsum eu gravida sollicitudin. Praesent orci augue, convallis id est congue, imperdiet fringilla lectus. Morbi congue metus lacus, id laoreet lorem posuere laoreet. Phasellus feugiat odio quam, consectetur dictum enim rhoncus a. Phasellus rhoncus tellus massa, ac gravida lacus auctor vel. + +Fusce finibus leo fringilla feugiat vulputate. Cras cursus rutrum tempor. Phasellus eu diam vitae tortor luctus maximus a id orci. Vivamus malesuada non ante nec hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam pulvinar id tellus quis faucibus. Nunc eros tellus, bibendum sed eleifend sit amet, euismod a turpis. In laoreet, nisl eu cursus ultricies, felis felis sodales ante, vel commodo velit ligula vel lorem. Praesent nisi velit, facilisis id blandit at, maximus id justo. Aenean malesuada ante eu nunc ornare suscipit. Nunc sollicitudin magna quam, gravida euismod dui egestas id. Integer accumsan, sem vitae ornare dignissim, purus ex semper nisl, a venenatis metus ligula sed magna. Nullam sollicitudin malesuada sollicitudin. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Aliquam eget tortor a magna iaculis imperdiet sed sed sem. Quisque scelerisque augue aliquam quam efficitur ultricies. Proin posuere lacus et est bibendum facilisis. Morbi in semper sem, vel sagittis purus. Nulla bibendum, lectus vel auctor porta, leo nibh tincidunt ipsum, id ultricies urna arcu egestas mauris. Duis vitae est at metus sodales pulvinar id eget elit. Aliquam fringilla leo vitae feugiat egestas. Phasellus elit nulla, luctus sed leo et, sollicitudin hendrerit elit. Suspendisse interdum ante eu viverra sodales. + +Maecenas dictum feugiat erat non convallis. Integer vestibulum tortor sit amet ante facilisis malesuada. Maecenas maximus dictum justo id blandit. Praesent ornare diam sed sem semper egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec maximus mattis laoreet. Phasellus fermentum semper tellus aliquam pharetra. Vivamus sed eros in tellus convallis rhoncus eu sit amet nisl. Duis quis vestibulum diam. Morbi posuere accumsan nisi, sit amet varius dolor suscipit nec. Duis porttitor purus sit amet turpis iaculis condimentum. Curabitur lacinia ut metus placerat ornare. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Quisque efficitur dolor id diam porttitor efficitur. Aenean venenatis tempus enim eget gravida. Integer ornare convallis lacus, id facilisis tellus lacinia id. Cras rutrum sollicitudin elit. Donec pharetra hendrerit augue vitae pellentesque. Vestibulum sollicitudin bibendum ante, non lobortis turpis ultrices at. Proin eget ornare ante, lacinia tempor risus. Nullam in arcu vel mi condimentum viverra. Integer diam sem, consequat vel consectetur vel, efficitur id purus. Suspendisse rhoncus, nisi eget hendrerit lacinia, ante metus suscipit eros, eu mollis quam risus ac ante. Aenean blandit congue eros, at facilisis elit bibendum id. + +Nulla nulla nunc, fermentum nec massa nec, sagittis sagittis lorem. Nullam nec accumsan libero, lobortis auctor libero. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vitae felis at leo lacinia ornare. Quisque tristique dignissim placerat. Sed porta turpis sit amet turpis scelerisque molestie sed ut lectus. In viverra cursus ex. + +Cras in dictum ante. Quisque commodo nisl nec risus gravida sagittis. Morbi in velit feugiat, molestie purus non, convallis ipsum. Suspendisse ut neque mattis, eleifend eros id, scelerisque metus. Aenean id egestas dolor. Aenean luctus quis dolor a hendrerit. Praesent maximus in orci vitae eleifend. Suspendisse potenti. In vestibulum enim ac lectus iaculis tempor. Nunc ac purus semper, suscipit est dapibus, rutrum nulla. Maecenas ac sem gravida, vestibulum nulla in, elementum est. Donec tellus odio, ullamcorper in malesuada eget, tempor scelerisque tellus. Donec nec dolor non lacus rutrum placerat. + +Sed luctus ex sit amet est fringilla, at faucibus justo condimentum. Maecenas dui augue, sollicitudin non arcu et, commodo bibendum nisl. Nulla in sem sit amet felis condimentum mattis. Donec eget felis ac neque pellentesque mollis. Suspendisse accumsan magna at massa aliquet, non finibus leo vehicula. Donec eget justo eget arcu aliquet facilisis. Quisque lobortis risus ut eleifend volutpat. Proin finibus, quam dignissim faucibus tempor, sapien nisi sagittis tortor, ut molestie ligula odio sed augue. Nulla eget fringilla eros. In luctus dui mauris, eget tristique enim aliquet nec. Mauris volutpat turpis ac nibh feugiat aliquet. Vivamus egestas orci magna, vel faucibus libero pretium efficitur. Phasellus elementum orci quis nisl luctus blandit ut ut ligula. Proin placerat consequat faucibus. Sed dolor ligula, eleifend id auctor vitae, sollicitudin vel diam. + +Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec eget quam a lorem laoreet vestibulum quis non nunc. Proin eleifend porta dui, non convallis arcu elementum ac. Aenean venenatis vehicula neque. Nulla mattis ullamcorper eros. Curabitur accumsan odio commodo metus auctor pharetra. Nam lobortis egestas dui, sit amet volutpat nisi semper sit amet. Ut blandit aliquam nisi, et hendrerit massa sodales at. Etiam mattis condimentum aliquet. In sem felis, pellentesque in quam accumsan, accumsan rutrum diam. Vivamus ligula quam, suscipit vitae nunc eget, condimentum pharetra enim. Aenean pretium euismod sapien. Pellentesque quis nulla gravida, luctus lacus sed, placerat erat. Suspendisse pretium est dui, et aliquet quam aliquet a. + +Vivamus malesuada dapibus eros, in lobortis lacus convallis ut. Aliquam maximus condimentum libero, vel vehicula enim congue sed. Duis quam arcu, scelerisque at lorem eget, finibus mollis velit. Sed fringilla odio sed tristique dictum. Nunc cursus ac ipsum non mattis. Aliquam dapibus porttitor sem, quis consequat ligula. Ut commodo vulputate dui in consequat. Curabitur lectus neque, mollis pharetra vestibulum nec, efficitur a purus. Fusce lacinia justo ac tortor pharetra, eget consectetur urna posuere. Vestibulum blandit eros nec odio faucibus, quis finibus massa mattis. Donec euismod felis in tincidunt ultrices. Integer id ullamcorper nisl. Phasellus vestibulum, augue in accumsan vestibulum, enim ante luctus nisi, vel sodales ex lectus id nibh. + +Donec ipsum mi, aliquet vitae varius nec, lobortis vel dui. Quisque vehicula nisl ipsum, vel porttitor tellus pulvinar sit amet. Sed at ultrices lectus. Morbi ac sapien enim. Sed mi tellus, cursus vitae lorem a, auctor aliquet ex. Nulla dapibus ex quis sapien tincidunt aliquet. Suspendisse nec porta elit. Maecenas ultrices fermentum neque at sagittis. Suspendisse vitae lacus non sapien elementum ullamcorper. Sed volutpat eleifend elit, at semper quam aliquam at. Sed efficitur tincidunt sapien ac auctor. Nam rutrum rhoncus augue, quis pharetra augue sollicitudin in. Ut placerat justo a felis feugiat, quis tincidunt augue faucibus. Sed metus ante, pulvinar vitae convallis convallis, auctor non neque. Sed gravida ultrices elementum. Mauris a convallis urna, in ullamcorper ex. + +Nulla vitae justo et lectus posuere rutrum ac id neque. Fusce ac vulputate nisl, eu dignissim urna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Maecenas fermentum odio at convallis pulvinar. Praesent pharetra tincidunt risus, convallis varius neque maximus non. Vivamus lobortis est a leo suscipit, quis pellentesque mi pharetra. Aliquam nec tempor arcu, non interdum urna. Morbi quis finibus mauris. Nulla tristique lobortis pretium. + +Integer egestas, tellus eu bibendum semper, diam lacus pellentesque nunc, a dignissim sapien est a sapien. Vestibulum augue nisl, euismod sed gravida eu, convallis id diam. Curabitur malesuada tristique eros sed facilisis. Morbi tortor libero, tincidunt nec lacus vitae, placerat varius elit. Nunc aliquam ex bibendum diam laoreet, ut scelerisque nisl ornare. Vivamus tempus hendrerit eros, nec malesuada nisl scelerisque eu. Quisque vel dui bibendum libero dapibus ullamcorper. Phasellus sollicitudin diam ac facilisis mollis. In malesuada eros velit, a volutpat mauris consectetur sit amet. Cras augue ante, efficitur fermentum pellentesque ac, vestibulum sit amet libero. + +Curabitur quis tortor in ligula dictum viverra vel at urna. Sed a est varius, lobortis tortor eget, elementum lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas tempus eu enim vitae pretium. Integer tempor felis urna, nec porttitor risus fringilla et. Mauris tincidunt mauris est, nec consectetur ante volutpat nec. Nam maximus convallis nulla eu aliquam. Proin ultricies sit amet turpis ac malesuada. Etiam elementum tortor quis pellentesque ultricies. Mauris feugiat accumsan consectetur. Maecenas tempor metus ut sem porttitor sodales. + +Ut aliquet hendrerit elit ac porta. Aliquam arcu tortor, facilisis quis felis id, mattis rutrum sapien. Sed volutpat purus mi, ac viverra purus pretium vel. Duis lectus leo, lobortis et lectus in, lobortis tincidunt turpis. Nulla et porta lacus. Curabitur mattis posuere ex et finibus. Etiam a luctus lacus, et ornare ligula. Proin ut lacinia est, ac aliquam augue. Vestibulum non laoreet nisl, sit amet porttitor sapien. Etiam sagittis laoreet est, ut efficitur felis. Aliquam purus nisi, bibendum id risus pulvinar, fermentum imperdiet felis. + +Vestibulum et diam nec leo eleifend pretium. In maximus neque quam, tincidunt consectetur risus feugiat sed. Nulla interdum dui tellus. Nam lobortis dolor eget imperdiet semper. Aliquam erat volutpat. Maecenas mi ex, efficitur quis faucibus eget, luctus quis elit. Sed in efficitur libero. + +Mauris tincidunt in neque ac dapibus. Donec cursus nisi mi, eu sodales ex ornare in. Curabitur euismod interdum quam ac tempor. Nam sollicitudin condimentum nunc, nec dictum tortor euismod sed. Nullam tortor nisi, pulvinar vitae vestibulum nec, malesuada ac mauris. Sed malesuada dignissim augue vitae cursus. Ut aliquet tristique urna, sit amet eleifend est sodales ac. Duis posuere, eros consequat aliquam iaculis, magna tortor fermentum justo, ut venenatis ligula libero ac lacus. Quisque sodales malesuada tristique. Aenean posuere nisl vel est tincidunt, vel tristique turpis bibendum. Vestibulum convallis accumsan condimentum. Curabitur fermentum congue eros, vel malesuada nisl. In leo nulla, vulputate id eros ac, rhoncus rhoncus lorem. Fusce eu posuere urna, ut porttitor leo. Suspendisse rutrum magna fringilla condimentum dignissim. + +Integer in mi leo. Fusce ut fringilla libero, ac ultricies ex. Aliquam interdum augue ac velit ullamcorper viverra dignissim non orci. Aliquam erat volutpat. In tempor et urna sed lacinia. Cras ullamcorper dapibus diam, non blandit eros posuere in. Curabitur tristique efficitur porta. Nulla vitae purus sodales, egestas ante vel, suscipit velit. Ut sagittis faucibus aliquet. Sed at nisl nunc. Ut eu dui at odio iaculis vehicula a suscipit justo. In dui est, ullamcorper vitae metus ut, eleifend consectetur justo. Proin rutrum est nec velit pellentesque tincidunt. Suspendisse a nulla sem. Integer sit amet mi id est commodo pulvinar eu vitae ante. + +Vivamus sed nibh accumsan, accumsan lorem vitae, scelerisque justo. Curabitur sit amet erat rutrum, pellentesque urna vel, ultricies massa. Suspendisse elit nisi, egestas eget scelerisque at, malesuada ultricies mauris. Mauris interdum nisl dapibus hendrerit scelerisque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean nulla dui, pellentesque convallis elementum ut, accumsan non tortor. Integer fringilla pellentesque posuere. Praesent viverra felis risus, ut fermentum ipsum dictum at. Suspendisse nibh libero, faucibus sed lacinia id, posuere fermentum mauris. Suspendisse vel lacus vulputate, venenatis nunc ut, elementum nibh. Maecenas rutrum lorem vitae ullamcorper porta. Etiam scelerisque, justo et interdum ullamcorper, neque turpis fermentum tellus, non scelerisque erat leo et odio. Vestibulum feugiat nulla non rhoncus vulputate. + +Etiam venenatis urna aliquet, pellentesque odio quis, venenatis nisl. Pellentesque accumsan tincidunt nibh, egestas vulputate purus suscipit eget. Pellentesque non nisi nisi. Nulla magna nisi, sodales non cursus eget, varius in nisl. Donec consectetur finibus tempus. Proin eget tempor dui. Maecenas quis facilisis risus. Integer nisl nulla, pellentesque eget suscipit at, pretium at metus. + +In vestibulum felis in nibh lobortis, eu cursus lectus varius. Ut a justo vitae purus tincidunt fermentum. Pellentesque non pulvinar eros. Sed lorem erat, pulvinar id diam nec, rhoncus placerat urna. Donec in posuere diam. Praesent faucibus ipsum vel est tempor dignissim. Vestibulum pellentesque ultrices finibus. Cras nisi orci, facilisis vel ultricies eu, accumsan a metus. Phasellus dui orci, accumsan non blandit efficitur, bibendum et erat. Aliquam tincidunt vestibulum vulputate. Donec vitae consequat magna. Etiam consectetur orci nec ex volutpat ornare. Pellentesque quis ex eu leo malesuada accumsan vel non arcu. Nunc blandit nisi quis ante pharetra imperdiet. Suspendisse elementum mi vitae erat faucibus, eget vestibulum mauris lacinia. Nam imperdiet nulla id egestas vehicula. + +Nunc quis purus fringilla, commodo quam eu, varius sem. Maecenas vehicula massa urna, nec ultricies augue accumsan nec. Etiam bibendum est eu posuere viverra. Morbi imperdiet sem eu risus viverra, ac pulvinar augue rhoncus. Nunc tortor mi, porta in sollicitudin tristique, bibendum sit amet ipsum. Vivamus sollicitudin, turpis blandit maximus venenatis, ipsum mi efficitur nibh, nec venenatis nulla est at ligula. Nulla ultrices est metus, eu iaculis tortor hendrerit nec. Nullam eget purus massa. Etiam eleifend dui et facilisis porta. Duis dignissim velit vitae velit consequat mollis. Morbi interdum auctor varius. In at tincidunt diam, ac bibendum leo. Donec vulputate, leo ut cursus gravida, ipsum magna pharetra ipsum, a fermentum neque mi at neque. Pellentesque magna ante, ultrices vel bibendum sit amet, pharetra tempus magna. Vivamus vel venenatis neque, a egestas orci. Integer posuere lorem vel euismod semper. + +Pellentesque sed ante vel libero semper ullamcorper. Morbi sapien risus, cursus sed cursus eu, vehicula quis mauris. Suspendisse eu accumsan orci, tincidunt laoreet sapien. Mauris ultrices turpis ac purus ullamcorper aliquam. Vestibulum nec vestibulum tortor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean venenatis vehicula rutrum. Pellentesque euismod fringilla velit non fringilla. Ut eleifend, magna eget interdum pellentesque, tortor sem mattis lacus, quis blandit quam sapien eleifend lacus. Vestibulum quis convallis lacus. Vestibulum porttitor eros ut risus venenatis facilisis. Aliquam sit amet nibh facilisis, cursus nisi nec, finibus felis. Integer id ante neque. Fusce tincidunt tincidunt quam. Praesent tristique commodo leo sit amet iaculis. + +In fringilla finibus enim, vitae vulputate mi tempus id. Phasellus laoreet neque justo, sed porttitor tortor rhoncus non. Vestibulum porttitor pretium ligula, efficitur interdum nunc bibendum nec. Integer dictum ut lectus et vestibulum. Aliquam quis egestas erat. Nulla facilisi. Nam sit amet sollicitudin nisl, tincidunt pharetra mi. + +Morbi blandit erat id sem convallis imperdiet. Aenean eleifend risus convallis pretium vehicula. Curabitur dolor arcu, fermentum eget diam ac, laoreet fringilla justo. Integer vitae purus ac neque euismod mollis. Donec ornare velit eget mauris aliquam aliquet. In hac habitasse platea dictumst. Fusce odio felis, tempor vel elit in, convallis suscipit neque. Nunc eu sem luctus, auctor tellus eget, condimentum massa. Aliquam erat volutpat. Suspendisse massa felis, pretium at rhoncus non, maximus nec libero. Pellentesque eu iaculis massa, id tempus est. In elementum dolor id ullamcorper dapibus. Nulla semper lorem ut molestie faucibus. Curabitur ac efficitur justo. Sed felis massa, interdum sed tellus sed, ultrices efficitur nunc. Duis facilisis urna fringilla fermentum semper. + +Nam porttitor eget dolor nec suscipit. Proin in tempus lorem, semper tempus ex. In molestie justo posuere libero porta gravida. Vivamus vel felis hendrerit, rutrum mauris eu, blandit ligula. Ut et eleifend tellus. Donec non neque at ligula maximus scelerisque non eget enim. Suspendisse potenti. Fusce tempor diam ante, nec sodales purus elementum placerat. Cras semper ullamcorper dui, nec feugiat justo consectetur at. Aenean tincidunt ligula sit amet arcu vestibulum luctus. Nullam quis vestibulum neque, vel suscipit urna. + +Nam sed tempor urna. Nunc dui lorem, blandit nec interdum in, fermentum sed est. Duis pellentesque ultrices dui vel venenatis. Fusce dignissim urna neque, vitae varius libero imperdiet eu. Quisque ut molestie nisi, ac bibendum justo. Vivamus vel tincidunt nibh. Morbi viverra lectus ac imperdiet venenatis. Vestibulum sodales diam risus. Nulla vulputate lacinia ligula sed aliquam. Aliquam et elit sed ante consequat vestibulum ac ac est. In accumsan, tortor id lacinia feugiat, purus libero sagittis dolor, vel dapibus magna orci vitae nulla. In vitae lectus viverra, pretium lectus ac, rutrum augue. Nulla a auctor felis. Morbi finibus feugiat urna ut varius. Curabitur placerat, arcu vitae congue volutpat, eros lectus sodales mauris, eu sagittis diam augue nec sapien. In aliquam eu metus ac malesuada. + +Donec nec nibh ac mi volutpat suscipit at eu quam. Aliquam erat volutpat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque tincidunt neque nec ligula eleifend dignissim. Donec vehicula sem a vestibulum lacinia. Sed in porta lorem, sed fringilla nisi. Suspendisse potenti. + +Nulla et leo eu ligula fringilla interdum. Proin mollis finibus vulputate. Mauris ultrices dolor sit amet venenatis fringilla. Sed elementum in nulla sit amet hendrerit. Nullam eleifend a velit rutrum sodales. Integer et pharetra nisi. Cras massa lectus, efficitur sed urna vel, finibus bibendum erat. + +Morbi et tristique justo, et lacinia metus. Integer sed erat varius, condimentum lorem ac, vulputate enim. Vestibulum a commodo metus. Maecenas quis cursus mauris. Donec nunc eros, aliquam pretium neque sit amet, tempor vestibulum nunc. Etiam eu tortor malesuada turpis porttitor pellentesque. In posuere suscipit augue sed vehicula. Sed posuere dignissim nibh, auctor finibus diam blandit eget. Phasellus at nisi vitae sapien pulvinar interdum vitae a leo. Donec bibendum mattis nisl, sit amet molestie sem porta non. + +Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque eu est vulputate, imperdiet diam quis, aliquam ipsum. Cras purus erat, accumsan in velit sed, euismod ullamcorper ex. Nullam lobortis rhoncus odio sit amet lacinia. Ut sit amet risus et enim iaculis ultrices et at nisi. Curabitur vulputate sapien neque, a porttitor ex volutpat in. Sed purus diam, posuere vitae aliquet nec, suscipit in orci. Sed condimentum justo egestas dapibus mollis. + +Nulla vitae sapien lacus. In maximus pellentesque purus, sit amet tincidunt massa scelerisque et. Mauris feugiat molestie est eu tempor. Praesent sit amet pharetra odio, in pellentesque diam. Aliquam placerat id tortor non sodales. Pellentesque vitae velit pharetra felis condimentum porta. Nunc molestie justo nec facilisis pellentesque. + +Morbi interdum eros vel dui ornare, a laoreet felis placerat. Vestibulum nec porta turpis. Proin accumsan massa turpis, non dignissim sem lacinia eu. Duis quis luctus leo. Vivamus fermentum orci et sapien dapibus faucibus ac sit amet nibh. Nam vel quam ac libero fringilla laoreet quis ut ipsum. Nulla sodales nisi diam, et semper nibh porttitor vel. Quisque rhoncus, metus id laoreet lacinia, ligula nibh maximus sem, vel sodales ex nulla et libero. Phasellus vitae sodales dui, et maximus lorem. Fusce rutrum augue quis nisi sagittis dictum. Duis mauris sem, feugiat a diam sit amet, pulvinar finibus nulla. + +Duis vel ex faucibus, suscipit mi at, vehicula justo. In in porttitor ex. Maecenas auctor bibendum tincidunt. Mauris faucibus aliquet nibh, quis laoreet sapien. Donec a erat dui. Nunc tincidunt, arcu id commodo porta, odio purus egestas eros, ut lacinia nunc tortor at sem. Duis commodo nisi at purus finibus, a venenatis enim pulvinar. Donec eu leo tincidunt, blandit neque ut, viverra orci. In hac habitasse platea dictumst. Etiam auctor, purus in elementum dictum, est mi elementum est, non iaculis augue massa sit amet purus. Nullam porttitor gravida sodales. Sed blandit, odio vehicula elementum aliquet, risus purus hendrerit ipsum, vel cursus massa magna non lacus. + +Suspendisse dapibus augue et arcu mattis, et malesuada nulla suscipit. Cras scelerisque molestie nibh, ac laoreet risus convallis lacinia. Mauris tempus ipsum et urna malesuada maximus. Nunc condimentum, mi id aliquam dictum, neque justo dictum urna, a egestas lectus felis eget turpis. Pellentesque luctus mi sed iaculis feugiat. Cras ornare ipsum orci. Phasellus pulvinar dignissim magna vitae euismod. Curabitur massa massa, interdum eget semper vel, semper nec mauris. Proin vestibulum diam magna, sit amet tempus purus pulvinar venenatis. Duis ac nunc sem. Nam suscipit, velit eget tempus porta, purus felis luctus enim, vitae malesuada risus elit eget quam. Sed malesuada lobortis purus consequat aliquet. Fusce luctus consequat diam. Interdum et malesuada fames ac ante ipsum primis in faucibus. + +Cras augue ex, imperdiet ac purus volutpat, dictum bibendum diam. Vestibulum tempor, sem id posuere semper, odio mi ultricies arcu, non vehicula eros urna vitae metus. Fusce vulputate est eu nibh venenatis, sit amet pellentesque mauris dictum. Ut turpis turpis, venenatis ac convallis sit amet, posuere quis nibh. Cras eget odio tincidunt, rhoncus sapien ut, rutrum ante. Aliquam tempus eget diam sed interdum. Proin a leo lacus. Aenean volutpat tincidunt justo, sagittis iaculis nibh. Suspendisse potenti. Nam semper quam ut sapien finibus, non ornare velit fermentum. Ut at leo mattis massa pretium finibus. Ut mi urna, cursus ut lorem vitae, vestibulum lobortis justo. Morbi vel blandit ligula. Praesent gravida fringilla diam eget hendrerit. Aenean cursus gravida posuere. Vestibulum in aliquam mi. + +Nullam tellus nisi, hendrerit sodales ligula ut, cursus suscipit ex. In a nisi lacinia, pellentesque est eget, pulvinar magna. Donec eu enim ornare, condimentum sem eget, vestibulum sem. Nulla nec ullamcorper ante, cursus tincidunt ex. Fusce ut nulla a magna viverra auctor. Proin ac elit eros. Donec nec purus at ligula porta condimentum. Curabitur laoreet magna eget rutrum luctus. Nulla tincidunt consequat lacus, id maximus nibh molestie eget. Nulla aliquet ligula mauris, ut interdum mauris rhoncus quis. Suspendisse sollicitudin laoreet finibus. Etiam dictum, lacus vitae porta lacinia, urna massa fermentum ligula, ut sodales mi nibh vel magna. Proin non urna non dolor maximus pellentesque. Phasellus non nulla non elit tristique elementum ac eget odio. Ut molestie, ex et vehicula blandit, purus ante dictum lectus, non fermentum magna mauris quis mauris. + +Curabitur ultrices posuere tristique. Nam gravida eget tellus a accumsan. Nam vulputate, sapien a placerat laoreet, nisi turpis elementum ipsum, eget rhoncus libero ante eu nunc. Fusce in augue id purus ullamcorper molestie sit amet a ipsum. Cras volutpat dapibus eleifend. Maecenas ut diam eu nibh pretium maximus. Mauris tristique hendrerit tempor. Nunc sit amet malesuada ligula, a interdum nulla. Vestibulum laoreet dapibus odio id laoreet. + +Quisque ac sagittis nibh. Curabitur vulputate purus nec augue placerat sollicitudin. Donec efficitur nec elit quis mollis. Cras dignissim tellus vitae magna semper, eu maximus nisi volutpat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut sodales, nunc a sollicitudin dignissim, lectus arcu ullamcorper erat, sed mattis neque nunc sit amet felis. Aenean quis lacus augue. Duis ut enim id ex pulvinar blandit. Nam commodo porttitor est sit amet consectetur. In fringilla vehicula odio, nec volutpat quam euismod eget. Curabitur finibus sollicitudin dui. Vivamus a velit sit amet lectus venenatis suscipit. Cras in justo id erat venenatis lobortis. Vestibulum ac tortor in lacus consectetur suscipit. Nam et urna in nulla commodo hendrerit nec id dui. + +Donec pulvinar sed ipsum tristique laoreet. Nullam euismod dignissim volutpat. Proin ac tortor fringilla, accumsan dolor sit amet, interdum lorem. Vivamus molestie nibh urna, et suscipit mauris fermentum eget. Vestibulum viverra, enim et tincidunt scelerisque, felis ex hendrerit magna, non consequat lectus nunc at neque. Suspendisse rhoncus, dui ut ultricies maximus, nisl enim vestibulum risus, sit amet varius urna est et neque. Cras malesuada est nunc. Cras gravida sed nunc at pharetra. Proin sit amet eleifend arcu, vel auctor felis. Nullam vel elit libero. Aenean mi risus, euismod ut suscipit sit amet, tincidunt auctor turpis. Duis volutpat quam suscipit, rhoncus purus eget, faucibus mauris. Ut aliquam arcu augue, nec mollis tellus vulputate et. Mauris viverra ex urna, eu elementum urna semper a. Nam quis dignissim nulla. Suspendisse nulla lorem, posuere vitae dui nec, rhoncus pretium eros. + +Sed at ex id ipsum euismod condimentum vitae et libero. Vivamus urna libero, mollis et erat sed, tempus rhoncus magna. Pellentesque libero ipsum, lacinia ac odio vitae, ullamcorper tincidunt velit. Aenean ipsum enim, semper ut accumsan nec, aliquet ac tortor. Donec fermentum, odio id porta pellentesque, orci enim gravida lacus, eget aliquam orci tortor nec leo. Pellentesque euismod cursus porta. Phasellus lorem tellus, fringilla sit amet dolor a, elementum mattis tortor. Curabitur tristique est ut nisi auctor, quis ultrices dui eleifend. Nam porta odio mauris, et posuere lectus lobortis ac. Mauris aliquam ac leo in blandit. Vivamus volutpat magna ac purus pretium, vel cursus risus accumsan. Mauris id odio ipsum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + +Pellentesque lacinia placerat turpis in facilisis. Aenean in risus eleifend, dapibus sapien non, tempor tellus. Proin condimentum tortor tristique aliquam faucibus. Donec mollis lorem ac ante tristique, ut bibendum dolor semper. Pellentesque ipsum nibh, tristique sit amet mattis eu, interdum nec enim. Nam hendrerit, purus et vehicula finibus, velit sapien viverra magna, et facilisis mauris dolor at nisi. Pellentesque feugiat quis neque vel ornare. Etiam bibendum, justo vitae dignissim scelerisque, nibh libero aliquet neque, id faucibus magna lectus a odio. Nunc sodales convallis eleifend. Fusce tincidunt ante in nisi blandit laoreet. Fusce efficitur, mauris non varius sodales, lacus urna fringilla enim, ac interdum justo eros ac augue. Curabitur et pharetra nisl, quis ultricies nulla. Nullam aliquet risus sit amet sollicitudin aliquam. Praesent scelerisque vestibulum orci, sed feugiat diam sollicitudin et. Pellentesque quam orci, sagittis sit amet tempor ornare, interdum ac diam. Aenean placerat nisl ex, nec accumsan orci semper eu. + +Praesent ut nulla vitae nisi pulvinar commodo sit amet quis lectus. Nullam scelerisque ac tortor in placerat. Maecenas tristique ligula lectus, quis fringilla urna bibendum quis. Nam elementum malesuada ullamcorper. Integer dapibus tincidunt congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Praesent ullamcorper metus scelerisque eleifend malesuada. Integer sodales, arcu at ultrices mollis, ex risus ultrices erat, et pellentesque lectus urna non ex. Proin dapibus faucibus commodo. In et bibendum orci, vitae fermentum ante. In dapibus arcu quis bibendum lobortis. Vivamus sagittis eleifend lacus, et posuere nisi tincidunt nec. + +Ut viverra finibus rutrum. Phasellus id sagittis libero. Phasellus mattis felis viverra ligula ultrices, eget ullamcorper tellus tincidunt. Fusce fringilla mi vitae ornare dapibus. In hac habitasse platea dictumst. Phasellus interdum eu turpis non blandit. Quisque ac congue magna, ac gravida ligula. Phasellus aliquet finibus libero vitae iaculis. Sed sit amet condimentum ex. Sed dapibus at ligula vel ultricies. + +Pellentesque placerat dui vitae ligula dapibus dignissim. Nulla semper aliquam varius. Donec et pretium orci. Aliquam eleifend tristique enim accumsan pellentesque. Phasellus sit amet nisi id ex sodales viverra. Donec fermentum commodo dolor, vulputate pellentesque sapien sodales sit amet. Maecenas id commodo nibh, at convallis mi. Morbi congue varius euismod. Nunc rutrum a metus ac semper. + +Integer sit amet ipsum sit amet diam iaculis lobortis ac eu lectus. Fusce consequat velit a ipsum aliquet faucibus. Vivamus in urna eget nisi elementum condimentum id et arcu. Mauris malesuada purus ultricies lectus vestibulum, a tempus nunc vestibulum. Fusce non tristique enim, sed auctor odio. Pellentesque purus mauris, iaculis non condimentum pellentesque, cursus luctus arcu. Integer id leo eu elit tristique elementum ac id purus. Fusce tincidunt iaculis convallis. Quisque ut vestibulum nulla, non convallis tortor. Curabitur libero mauris, laoreet sit amet magna in, vestibulum interdum magna. Praesent sed arcu ultrices, sodales diam non, posuere tellus. Donec ante purus, hendrerit in finibus id, luctus et urna. + +Phasellus sed vulputate diam. Cras a libero nibh. Etiam pulvinar diam at fermentum ultricies. Ut placerat ipsum sed mi accumsan, rutrum ornare dolor volutpat. Nullam ac pellentesque nibh, vel convallis sem. Ut tellus lectus, malesuada sit amet ligula vitae, aliquet condimentum magna. Phasellus lobortis, felis eu tempor scelerisque, urna sapien placerat enim, sit amet rutrum turpis felis a diam. Sed eget diam nec mauris ullamcorper interdum sagittis at elit. Aenean ac felis dignissim, facilisis diam mattis, sagittis dolor. Duis lobortis sodales urna, vitae porttitor mauris. Vestibulum mollis viverra rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Cras nec bibendum ante, non pulvinar dolor. + +Ut commodo et tellus suscipit volutpat. Donec auctor turpis tortor, sed hendrerit elit facilisis et. Nullam dolor eros, gravida non consequat nec, aliquet nec ante. In viverra aliquam vestibulum. Nunc sit amet mauris rhoncus, bibendum nisl sit amet, malesuada risus. Aliquam id ex ac dui volutpat cursus. Donec sit amet sem elit. + +Integer tempor eget magna porttitor consequat. Duis efficitur libero a nisl pellentesque, quis ullamcorper nibh tincidunt. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Proin sollicitudin, elit sed lobortis tempus, neque risus egestas sem, eget commodo lacus lacus quis lorem. Quisque faucibus arcu sapien, in auctor est egestas non. Nam sed metus quis ligula sodales convallis. Quisque eros enim, consequat in malesuada eget, vehicula nec nunc. Vestibulum faucibus dui sed lectus euismod, sed lacinia nibh blandit. Morbi blandit neque quis diam efficitur pellentesque sit amet quis ante. Proin tincidunt dolor in quam ultrices, facilisis finibus ligula vehicula. In massa quam, sollicitudin ac vestibulum vel, viverra id nisl. Suspendisse suscipit imperdiet justo, tempus finibus erat dignissim id. Donec nec arcu suscipit, congue lacus a, varius lectus. + +Vestibulum convallis nulla sit amet est ultrices, sed suscipit ligula hendrerit. Fusce vel elit placerat, posuere enim ut, egestas turpis. Pellentesque vitae nulla pellentesque, gravida risus id, eleifend elit. Nunc eu commodo enim. Vestibulum erat eros, varius non fringilla sed, consectetur et sapien. Maecenas sed lacus mi. Mauris quam enim, semper ut porttitor vitae, dictum nec libero. Cras fermentum laoreet lectus, luctus pellentesque massa suscipit vitae. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nunc magna, vestibulum non massa dapibus, porttitor efficitur tellus. Fusce ornare interdum orci, non viverra est pharetra et. Donec nisl lorem, posuere eget laoreet et, bibendum quis erat. Ut pharetra, ex ut aliquam iaculis, nisl nunc rhoncus diam, vitae tempor ligula ligula sit amet mauris. Praesent elementum congue arcu a convallis. Cras porta, mauris non aliquet fringilla, lectus mauris pellentesque nisi, et pharetra sapien mauris ac lectus. Proin pellentesque nunc ut elit lobortis semper. Sed tortor urna, malesuada elementum dolor non, pellentesque malesuada dolor. Vivamus et arcu non purus gravida vulputate et vel ipsum. Etiam rhoncus, diam ac ultrices vehicula, mauris ante malesuada mauris, eu consequat enim nisl ut libero. Mauris sollicitudin, diam non efficitur fermentum, velit diam pellentesque lorem, id rhoncus mi mauris id arcu. Mauris accumsan lacus a magna sagittis, sed laoreet lorem vehicula. Nullam porta, justo nec pellentesque tincidunt, urna eros egestas leo, dictum viverra enim lectus vitae velit. Suspendisse potenti. Aliquam at purus commodo, lobortis nisi quis, ultricies velit. + +Suspendisse eros erat, porta ut consequat in, gravida et velit. Mauris arcu arcu, porttitor et lectus ut, vehicula vestibulum turpis. Morbi id rhoncus erat. Duis eu nunc vitae magna bibendum molestie. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas et rutrum odio. Proin vulputate maximus nulla, vitae aliquam mauris facilisis ut. Suspendisse dapibus nibh eget dui aliquam viverra. Etiam laoreet massa eget consequat dapibus. Morbi ultrices elit sed nibh tincidunt, iaculis tempor magna efficitur. Fusce hendrerit elementum vehicula. Aenean imperdiet varius felis. Nam tempus sodales molestie. + +Donec quis augue cursus, congue purus eget, mattis lectus. Proin iaculis neque eget lectus maximus dictum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed eu convallis est, sit amet scelerisque orci. Curabitur a orci vitae urna sodales ullamcorper. Vivamus non ornare enim. Sed mi erat, porttitor non porttitor vitae, auctor at nisi. + +Vivamus vitae nulla id quam vulputate fermentum. Cras accumsan dui sed ligula fermentum tempus. Aliquam erat volutpat. In ac fermentum quam. Integer ac mollis dui, quis ornare erat. Aenean elementum justo eu hendrerit semper. Cras tempor interdum tristique. + +Duis pharetra vel magna scelerisque euismod. Integer pretium neque at magna euismod, eu faucibus magna sollicitudin. Curabitur sit amet purus non ligula sollicitudin dapibus sed sit amet tellus. Proin ut iaculis tortor. Suspendisse efficitur, quam sit amet tempor volutpat, nunc est interdum eros, sed pharetra velit nibh vel lectus. Vestibulum sapien orci, elementum et urna sit amet, lobortis vulputate sem. Vestibulum laoreet laoreet nunc eu pretium. Vivamus rutrum vitae justo vitae semper. Sed ornare rutrum dolor, eget luctus elit finibus nec. Cras vitae sollicitudin tellus. Donec consectetur enim non risus dignissim molestie. Aenean pulvinar faucibus dictum. + +Mauris egestas risus non orci luctus maximus. Proin vehicula vel est quis dignissim. Donec convallis imperdiet quam in blandit. Mauris sit amet urna at nisl aliquet condimentum. Sed justo ex, lobortis vitae neque eu, ultrices tincidunt mauris. Ut ac enim arcu. Vestibulum elementum eros id ipsum placerat, vel porta nulla viverra. Phasellus lacinia nunc ac odio bibendum, et finibus ipsum consequat. Vivamus eget augue at diam imperdiet dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce et bibendum nisi, eu tempus orci. Donec convallis leo at efficitur rhoncus. Integer et lacinia dui. Phasellus faucibus purus pretium turpis vestibulum, a convallis neque iaculis. Nulla in posuere orci, sed semper urna. + +Donec urna orci, dapibus ut vestibulum nec, scelerisque feugiat sem. Aenean nulla turpis, sollicitudin vel vehicula eu, tempor vel justo. Vivamus nec fringilla libero. Etiam odio dui, luctus id ex ac, fringilla vestibulum sapien. Duis eu porta diam, eu scelerisque ipsum. Cras porttitor pulvinar viverra. Praesent finibus, nibh ultrices dictum malesuada, nisi neque rhoncus eros, non porta justo justo sit amet dui. Nunc tincidunt tempor ante quis rutrum. + +Pellentesque rutrum semper dolor vitae ultricies. Fusce lobortis nisi a tincidunt pharetra. Nulla facilisi. Vivamus iaculis velit ipsum, non sagittis dolor egestas eu. Morbi nec libero euismod, gravida nisl id, maximus mauris. Phasellus venenatis dignissim semper. Morbi condimentum, elit in volutpat congue, mauris mi congue metus, eu gravida augue orci at tellus. Etiam vitae interdum mi. + +Aliquam sed orci in mi malesuada faucibus id vitae erat. Praesent scelerisque lobortis vehicula. Donec ac eros magna. Maecenas facilisis sed arcu vel lobortis. Nulla placerat sollicitudin libero eget sodales. Nullam a ex faucibus, dictum tortor sit amet, hendrerit erat. Morbi eu vehicula nibh, eu luctus dolor. Aenean efficitur, mauris non molestie facilisis, odio nibh rutrum turpis, interdum commodo ex orci et velit. Morbi nec massa a justo suscipit sollicitudin. Quisque sed est justo. Aenean a efficitur nisi. Aliquam condimentum lectus sit amet turpis interdum facilisis. + +Quisque vel scelerisque tortor. Nam laoreet iaculis lacus vitae consectetur. Proin ut erat nec erat bibendum scelerisque vitae id lorem. Nunc hendrerit ante eros, in venenatis ante euismod nec. Integer egestas urna nibh, ut sagittis leo tincidunt sed. Pellentesque vitae tempus neque. Cras et urna at ex posuere tristique a a elit. Donec in neque non enim accumsan blandit vel ut lectus. Nulla pharetra viverra mauris non consequat. + +Donec vel mollis eros, sit amet posuere lorem. Donec quis hendrerit lorem. Vestibulum ultricies tortor est, convallis placerat augue bibendum a. Quisque congue justo sit amet eros posuere eleifend. Integer dui odio, dapibus sit amet finibus nec, auctor quis ante. Nam a nisi ut quam ornare ornare et a nibh. Curabitur consectetur pellentesque nunc vitae iaculis. Vestibulum ornare libero metus, a sagittis eros eleifend vel. Curabitur auctor turpis vel tempor elementum. In dignissim, risus vitae vehicula tempus, massa mi feugiat purus, ut interdum velit turpis at augue. Etiam turpis eros, fermentum vitae tincidunt a, hendrerit quis diam. Praesent semper ultricies sapien quis vestibulum. + +Nunc aliquet massa quis sagittis convallis. Curabitur erat dui, tempus a leo non, scelerisque consequat diam. Phasellus imperdiet eros eget efficitur convallis. Nunc nec scelerisque elit, eu condimentum justo. Curabitur suscipit vehicula eros sed dapibus. Integer id neque malesuada, aliquam velit ac, tincidunt turpis. Quisque tempor consequat nibh quis varius. Nunc vel tortor efficitur neque consectetur finibus et vitae leo. Curabitur sit amet tortor lacus. Aenean euismod a nulla non sodales. Integer varius ipsum sit amet turpis blandit volutpat. Aenean nec leo augue. Curabitur non diam varius, egestas diam et, tincidunt nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. + +Morbi iaculis, purus eu hendrerit tempor, est quam vestibulum dui, nec fringilla dolor dui et magna. Aliquam id metus faucibus, volutpat ex a, volutpat dolor. Suspendisse bibendum ornare risus at malesuada. Nulla porttitor varius ultrices. Curabitur nunc enim, euismod eget rutrum at, mattis vel nisi. Phasellus placerat enim risus, in pellentesque risus fermentum gravida. Suspendisse potenti. Cras sodales mauris ut cursus pellentesque. Proin sodales justo tincidunt risus varius molestie. Nunc ligula magna, lacinia ac ante gravida, ullamcorper tempor ligula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum in tortor a arcu viverra faucibus quis ut lectus. + +Sed mattis mattis tellus ut suscipit. Duis finibus purus vel magna iaculis dignissim. Suspendisse at bibendum enim, non semper tortor. Duis sit amet ante neque. Integer hendrerit, leo eu ultricies pharetra, tortor lorem sagittis lacus, at aliquam ante metus eu lectus. Nulla sit amet aliquet neque. Aliquam vitae aliquet lacus. Cras efficitur odio non mollis sollicitudin. Nunc augue nisl, vehicula et maximus eget, laoreet non sapien. + +Nullam convallis placerat leo, non lacinia magna dictum quis. Sed non dolor tellus. Cras posuere dui id elit vestibulum, sit amet ullamcorper magna maximus. Phasellus blandit lectus in quam ullamcorper, sed vestibulum nulla egestas. Mauris eget condimentum ipsum. Phasellus vulputate magna vitae magna laoreet suscipit. Donec auctor, ante feugiat fringilla sagittis, nisl risus mollis purus, nec varius mauris erat at metus. Sed vel bibendum purus. Aliquam ut nunc viverra, vehicula nibh at, feugiat sem. Nam lorem dolor, auctor at maximus ac, malesuada in orci. Proin faucibus mattis magna a euismod. + +Quisque ac est blandit lorem hendrerit pharetra. Cras dapibus finibus sodales. Praesent fringilla venenatis ante id vehicula. Vestibulum eget iaculis nunc. Quisque pellentesque purus ac sapien pellentesque tincidunt. Quisque eget mi suscipit, imperdiet tellus eget, tempus purus. Nullam hendrerit erat eu dui hendrerit, et elementum ante aliquam. Mauris mattis fermentum ante non facilisis. Vivamus elementum sagittis accumsan. Ut vestibulum magna laoreet erat imperdiet iaculis. Integer elementum ut sem in ullamcorper. Curabitur venenatis leo eget nibh consectetur vestibulum. + +Phasellus sagittis quis nisi a interdum. Maecenas magna tortor, pellentesque quis porta quis, dignissim sit amet justo. Cras et ornare risus, et lobortis nisi. Proin ac efficitur nisl, eu laoreet nibh. Donec fermentum dolor in ligula dignissim, et convallis justo pretium. Suspendisse scelerisque et lectus in sagittis. Praesent eu mi rutrum, ultricies erat quis, porta libero. Praesent ultrices, arcu venenatis interdum porttitor, turpis mi commodo nisi, ut interdum augue lectus at orci. Nam sagittis pretium magna, ac euismod sapien semper condimentum. Mauris consectetur facilisis lectus, sollicitudin sollicitudin nisi euismod at. Pellentesque vehicula sit amet nulla a finibus. Donec tellus leo, cursus at nunc non, rhoncus dignissim lectus. Pellentesque sit amet libero et neque finibus accumsan. Vivamus efficitur lacus porttitor, ullamcorper neque vitae, facilisis ipsum. Quisque tincidunt tincidunt quam ac pulvinar. Donec dignissim gravida sapien, at venenatis elit vehicula a. + +Duis sit amet dapibus libero. Nulla facilisi. Nullam facilisis lectus sit amet odio rhoncus, ut dapibus odio aliquet. Quisque laoreet sed turpis ut maximus. Nunc pulvinar ante vehicula urna vestibulum, at mollis risus vehicula. Sed tempus pharetra erat semper ornare. Curabitur vitae dapibus lacus. Suspendisse id tristique ante, et condimentum augue. Sed eu nunc at elit rutrum consequat. Vestibulum ornare fringilla sapien, eget tincidunt turpis pretium ultricies. Nunc ac nunc risus. Phasellus euismod ipsum justo, ut accumsan libero tempus sit amet. + +Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus vestibulum ipsum sit amet tincidunt tempus. Vestibulum gravida tempor urna, facilisis aliquet libero eleifend egestas. In laoreet eu augue pretium maximus. Duis ac porta enim, ut scelerisque leo. Duis egestas ligula eu nulla cursus, nec rutrum enim hendrerit. Praesent accumsan est at justo euismod feugiat iaculis eu leo. Nulla et pulvinar justo, in pretium ex. Maecenas ac nisl quis justo efficitur dignissim nec a justo. Fusce dapibus congue odio. Vivamus et ligula diam. Fusce in porttitor magna, vehicula porta massa. Fusce eu mattis tortor. Etiam tristique rhoncus dui, nec ullamcorper quam dictum nec. Nullam feugiat sagittis condimentum. + +Suspendisse venenatis, purus id posuere bibendum, lacus dolor dignissim dolor, at blandit nibh lectus sit amet mauris. Curabitur convallis tempor egestas. Sed ut lectus ligula. Donec auctor dapibus velit sed sagittis. Aenean ultrices sem quis consequat viverra. Nunc malesuada, sapien et egestas cursus, neque erat pretium felis, sed accumsan mauris nunc facilisis eros. Nulla quis nibh ligula. Donec non sapien nulla. Sed pellentesque tortor eu odio volutpat, ac tempor metus sagittis. Pellentesque consequat mollis arcu vel pulvinar. + +Quisque ultrices volutpat vulputate. Vivamus ut dui hendrerit, consectetur neque vel, accumsan purus. Curabitur volutpat gravida tellus, vitae rhoncus sem semper a. Donec nec eros et augue rhoncus tincidunt. Ut eget leo blandit, vehicula justo non, ultrices nisl. Ut enim massa, sollicitudin at nisl non, tincidunt mollis sem. Nunc vel nunc id sem sollicitudin ornare non convallis ipsum. Aliquam porta ut purus vitae sagittis. Suspendisse ac odio diam. Morbi mi lorem, rutrum vel est sit amet, congue molestie nisl. Nulla commodo dui ante, sed ornare nisi sagittis ut. Nunc volutpat, augue ut sodales imperdiet, quam eros sollicitudin nibh, sed malesuada mi nunc et arcu. + +Praesent ut gravida lectus, eget efficitur sem. Nam facilisis iaculis rhoncus. Morbi euismod sagittis orci eu fermentum. Maecenas ut pharetra augue. Sed interdum mi mi, quis dignissim ante varius eu. Aliquam erat volutpat. Nulla et iaculis sapien, egestas finibus enim. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. + +Aenean in justo sagittis, lobortis elit vel, sagittis odio. Morbi tristique, sem vitae lobortis lacinia, lectus elit mattis sapien, vitae tristique ante felis eu quam. Integer rutrum ultricies lectus eu lobortis. Proin gravida elementum tellus vitae aliquam. Vestibulum erat turpis, dignissim non pharetra vitae, lacinia et nisi. Fusce elit nisl, feugiat sit amet nibh ac, porttitor convallis diam. Curabitur ac pulvinar ipsum. Duis quis faucibus neque, at sagittis tortor. Etiam pellentesque vitae tortor et tincidunt. Proin sem ligula, cursus ut nulla eget, rutrum sollicitudin nunc. Etiam vel consectetur erat. Nulla vitae est dui. + +Curabitur at scelerisque lorem. Nunc tincidunt vulputate interdum. Etiam elementum nibh massa, a volutpat mauris egestas sit amet. Vestibulum iaculis blandit lorem at blandit. Integer vel tempor velit, quis euismod erat. Vestibulum hendrerit augue sit amet nisl accumsan, nec ullamcorper enim molestie. Donec facilisis sodales finibus. Praesent viverra ut leo sed consequat. Mauris sed augue ornare, tempus lorem id, luctus mauris. Mauris eu neque vitae ex sodales pharetra id ut lacus. Nulla laoreet purus ipsum. Nullam dui lectus, maximus in ultricies nec, porttitor non eros. Maecenas urna leo, volutpat in bibendum nec, scelerisque eu augue. Maecenas bibendum pulvinar fermentum. Quisque vulputate sed magna nec volutpat. + +Aenean egestas commodo augue, nec dapibus enim sollicitudin sit amet. Aenean lectus enim, condimentum quis porttitor vitae, accumsan id odio. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris dapibus vel nulla at congue. Vestibulum quis mauris a ante dignissim consectetur nec a metus. Curabitur facilisis lorem orci, sed vulputate elit porttitor non. Vestibulum vitae lacus eleifend tortor auctor mattis et eu ligula. Nulla suscipit iaculis volutpat. + +In sed ligula ante. Duis euismod sed augue sit amet ultricies. Nunc sollicitudin, libero porttitor sodales eleifend, enim sapien convallis massa, ac euismod ex lacus ut nibh. Quisque iaculis risus nec cursus lacinia. Maecenas sed ipsum ligula. Morbi sodales est non velit cursus, sed sagittis ipsum luctus. Nam eu lacinia eros. Vestibulum hendrerit nec turpis at lobortis. In suscipit auctor felis, ac consectetur eros rutrum ut. + +Sed accumsan erat enim, sed tristique dolor sagittis ac. Quisque scelerisque efficitur nisi ut rhoncus. Praesent euismod, felis nec semper porttitor, odio felis congue lacus, in vulputate nunc ligula sed elit. Donec rutrum lectus sem, nec efficitur felis molestie quis. Aliquam euismod volutpat ligula, vel varius metus feugiat quis. Nulla facilisi. Nulla facilisi. Cras pulvinar ante nulla, id auctor magna suscipit nec. Morbi dictum euismod sapien sit amet iaculis. Duis velit tellus, tincidunt id sagittis sed, placerat aliquam velit. Aliquam neque orci, fringilla vel erat et, consectetur commodo velit. Aliquam erat volutpat. Mauris eget libero et risus laoreet fringilla. Nulla dignissim risus eget erat commodo elementum. Curabitur nec risus magna. + +Ut at imperdiet arcu. Suspendisse pulvinar est ut euismod dictum. Etiam ante purus, venenatis eget ullamcorper vitae, euismod sit amet ligula. Morbi egestas tortor sed metus sodales eleifend. Nunc lectus felis, suscipit sed felis sed, dapibus venenatis erat. Sed sagittis vitae quam vitae semper. Duis leo mauris, lobortis sed ante ut, consequat blandit justo. Vivamus feugiat tempor aliquam. Donec dapibus sed nunc sed iaculis. Aenean porttitor eros purus, nec ultricies leo rhoncus eu. Cras sit amet nisl mollis nunc tincidunt aliquet. Nulla pulvinar, ante in semper condimentum, tellus risus porta diam, vitae venenatis ante nibh nec dui. Quisque ante metus, convallis vitae enim quis, tincidunt consequat nisl. Duis euismod felis velit, nec sodales neque facilisis vel. Cras cursus pellentesque congue. diff --git a/timestamp.go b/timestamp.go @@ -0,0 +1,106 @@ +package msgpack + +import ( + "fmt" + "time" +) + +type Timestamp struct { + seconds int64 + nanoseconds int +} + +var _ Extension = (*Timestamp)(nil) + +func NewTimestamp(t time.Time) *Timestamp { + return &Timestamp{ + seconds: t.Unix(), + nanoseconds: t.Nanosecond(), + } +} + +func (t *Timestamp) Time() time.Time { + return time.Unix(t.seconds, int64(t.nanoseconds)).UTC() +} + +func (t *Timestamp) EncodeMsgpackExt(e *Encoder) { + if t.seconds>>34 == 0 { + if t.nanoseconds == 0 && t.seconds>>32 == 0 { + t.serialize32(e) + } else { + t.serialize64(e) + } + } else { + t.serialize96(e) + } +} + +func (t *Timestamp) DecodeMsgpackExt(d *Decoder, typ int8, size int) error { + if typ != t.Type() { + return fmt.Errorf("encoding/msgpack: timestamp: invalid type: %d", typ) + } + switch size { + case 4: + s, err := d.deserialize32() + if err != nil { + return err + } + *t = Timestamp{ + seconds: int64(s), + } + case 8: + v, err := d.deserialize64() + if err != nil { + return err + } + *t = Timestamp{ + nanoseconds: int(v >> 34), + seconds: int64(v & 0x00000003ffffffff), + } + case 12: + ns, err := d.deserialize32() + if err != nil { + return err + } + s, err := d.deserialize64() + if err != nil { + return err + } + *t = Timestamp{ + nanoseconds: int(ns), + seconds: int64(s), + } + default: + return fmt.Errorf("encoding/msgpack: timestamp: invalid size: %d", size) + } + return nil +} + +func (t *Timestamp) Type() int8 { + return -1 +} + +func (t *Timestamp) Size() int { + if t.seconds>>34 == 0 { + if t.nanoseconds == 0 && t.seconds>>32 == 0 { + return 4 + } else { + return 8 + } + } else { + return 12 + } +} + +func (t *Timestamp) serialize32(e *Encoder) { + e.serialize32(uint32(t.seconds)) +} + +func (t *Timestamp) serialize64(e *Encoder) { + e.serialize64(uint64(t.nanoseconds<<34) | uint64(t.seconds&0x3ffffffff)) +} + +func (t *Timestamp) serialize96(e *Encoder) { + e.serialize32(uint32(t.nanoseconds)) + e.serialize64(uint64(t.seconds)) +} diff --git a/uuid.go b/uuid.go @@ -0,0 +1,49 @@ +package msgpack + +import ( + "errors" + + "github.com/google/uuid" +) + +const ( + uuidType int8 = 127 +) + +// UUID wraps google's UUID and implements encoding/msgpack.Extension. +type UUID struct { + uuid.UUID +} + +var _ Extension = (*UUID)(nil) + +func (u *UUID) EncodeMsgpackExt(e *Encoder) { + e.Raw(u.UUID[:]) +} + +func (u *UUID) DecodeMsgpackExt(d *Decoder, typ int8, size int) error { + if typ != uuidType { + return errors.New("uuid: invalid type") + } + if size != 16 { + return errors.New("uuid: invalid uuid") + } + + var p = make([]byte, 16) + + err := d.Raw(p) + if err != nil { + return err + } + + copy(u.UUID[:], p) + return nil +} + +func (u *UUID) Type() int8 { + return uuidType +} + +func (u *UUID) Size() int { + return 16 +} diff --git a/uuid_test.go b/uuid_test.go @@ -0,0 +1,53 @@ +package msgpack + +import ( + "bytes" + "testing" + + "github.com/google/uuid" +) + +type uuidTestCase struct { + in string + out []byte +} + +var tests = []uuidTestCase{ + {"f47ac10b-58cc-4372-8567-0e02b2c3d479", []byte{ + 0xd8, 0x7f, // header + 0xf4, 0x7a, 0xc1, 0x0b, 0x58, 0xcc, 0x43, 0x72, + 0x85, 0x67, 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, + }}, +} + +func TestUUIDMarshal(t *testing.T) { + for _, test := range tests { + raw, err := uuid.Parse(test.in) + if err != nil { + t.Errorf("parse failed: %s, %s", test.in, err.Error()) + continue + } + + wrapped := &UUID{raw} + got := Marshal(wrapped) + if !bytes.Equal(got, test.out) { + t.Errorf("marshal failed; got: %v, want: %v", got, test.out) + } + } +} + +func TestUUIDUnmarshal(t *testing.T) { + for _, test := range tests { + wrapped := &UUID{} + + err := Unmarshal(test.out, wrapped) + if err != nil { + t.Errorf("marshal failed; err: %s", err.Error()) + continue + } + + if wrapped.String() != test.in { + t.Errorf("marshal failed; got: %v, want: %v", wrapped.String(), test.in) + } + } +} diff --git a/value.go b/value.go @@ -0,0 +1,23 @@ +package msgpack + +type Array interface { + EncodeMsgpackArray(e *Encoder) + DecodeMsgpackArray(d *Decoder, length int) error + + Len() int +} + +type Map interface { + EncodeMsgpackMap(e *Encoder) + DecodeMsgpackMap(d *Decoder, size int) error + + Size() int +} + +type Extension interface { + EncodeMsgpackExt(e *Encoder) + DecodeMsgpackExt(d *Decoder, typ int8, size int) error + + Type() int8 + Size() int +}