diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29b34df..bab31a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,14 +18,14 @@ jobs: strategy: matrix: - otp_version: [22,23,24] + otp_version: [26,27,28] os: [ubuntu-latest] container: image: erlang:${{ matrix.otp_version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compile run: make - name: Test diff --git a/GNUmakefile b/GNUmakefile index ef0b6de..6410f59 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -41,5 +41,5 @@ test: $(REBAR) ## Doc targets ## edoc: $(REBAR) - $(REBAR) edoc + $(REBAR) ex_doc diff --git a/doc/.build b/doc/.build new file mode 100644 index 0000000..3303377 --- /dev/null +++ b/doc/.build @@ -0,0 +1,29 @@ +404.html +api-reference.html +dist/handlebars.runtime-NWIB6V2M.js +dist/handlebars.templates-K7URE6B4.js +dist/html-PVRIOB7F.js +dist/html-erlang-4IXSOGMD.css +dist/inconsolata-latin-400-normal-RGKDDNDD.woff2 +dist/inconsolata-latin-700-normal-DTS2D7TO.woff2 +dist/inconsolata-latin-ext-400-normal-K7HVGTP7.woff2 +dist/inconsolata-latin-ext-700-normal-4MPBLFZC.woff2 +dist/inconsolata-vietnamese-400-normal-IGQPHHJH.woff2 +dist/inconsolata-vietnamese-700-normal-LHEGSN35.woff2 +dist/lato-latin-300-normal-YUMVEFOL.woff2 +dist/lato-latin-400-normal-W7754I4D.woff2 +dist/lato-latin-700-normal-2XVSBPG4.woff2 +dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 +dist/lato-latin-ext-400-normal-N27NCBWW.woff2 +dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 +dist/remixicon-NKANDIL5.woff2 +dist/search_data-3FEDF90C.js +dist/sidebar_items-C002F7F1.js +index.html +license.html +readme.html +ringbuffer.html +ringbuffer_app.html +ringbuffer_process.html +ringbuffer_sup.html +search.html diff --git a/doc/404.html b/doc/404.html new file mode 100644 index 0000000..f602822 --- /dev/null +++ b/doc/404.html @@ -0,0 +1,160 @@ + + + + + + + + + + + + + 404 — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ + +

+ Page not found +

+ +

Sorry, but the page you were trying to get to, does not exist. You +may want to try searching this site using the sidebar + + or using our API Reference page + +to find what you were looking for.

+ +
+
+
+ + + diff --git a/doc/api-reference.html b/doc/api-reference.html new file mode 100644 index 0000000..e763d6f --- /dev/null +++ b/doc/api-reference.html @@ -0,0 +1,230 @@ + + + + + + + + + + + API Reference — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ + +
+

+ + + + View Source + + + + API Reference ringbuffer v1.2.0+build.18.refca920a0 +

+ + +
+

+ + + + Modules +

+ +
+
+
+ ringbuffer + +
+ +

Ringbuffer implements a length limited queue. In systems this is often implemented as a ring, or cylic, buffer. Where the writer can push the reader ahead if the buffer is full.

+ +
+
+ + +

RingBuffer application

+ +
+
+ + +

Process to own the created ets table for the ring buffer.

+ +
+
+ + +

Supervisor for the ring buffers processes.

+ +
+ +
+
+ + +
+ + + +
+
+
+ + + diff --git a/doc/dist/handlebars.runtime-NWIB6V2M.js b/doc/dist/handlebars.runtime-NWIB6V2M.js new file mode 100644 index 0000000..117dc6c --- /dev/null +++ b/doc/dist/handlebars.runtime-NWIB6V2M.js @@ -0,0 +1,30 @@ +/**! + + @license + handlebars v4.7.7 + +Copyright (C) 2011-2019 by Yehuda Katz + +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. + +*/(function(r,e){typeof exports=="object"&&typeof module=="object"?module.exports=e():typeof define=="function"&&define.amd?define([],e):typeof exports=="object"?exports.Handlebars=e():r.Handlebars=e()})(this,function(){return function(u){var r={};function e(n){if(r[n])return r[n].exports;var t=r[n]={exports:{},id:n,loaded:!1};return u[n].call(t.exports,t,t.exports,e),t.loaded=!0,t.exports}return e.m=u,e.c=r,e.p="",e(0)}([function(u,r,e){"use strict";var n=e(1).default,t=e(2).default;r.__esModule=!0;var f=e(3),a=n(f),i=e(36),l=t(i),h=e(5),v=t(h),P=e(4),H=n(P),C=e(37),E=n(C),I=e(43),o=t(I);function g(){var y=new a.HandlebarsEnvironment;return H.extend(y,a),y.SafeString=l.default,y.Exception=v.default,y.Utils=H,y.escapeExpression=H.escapeExpression,y.VM=E,y.template=function(p){return E.template(p,y)},y}var w=g();w.create=g,o.default(w),w.default=w,r.default=w,u.exports=r.default},function(u,r){"use strict";r.default=function(e){if(e&&e.__esModule)return e;var n={};if(e!=null)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n},r.__esModule=!0},function(u,r){"use strict";r.default=function(e){return e&&e.__esModule?e:{default:e}},r.__esModule=!0},function(u,r,e){"use strict";var n=e(2).default;r.__esModule=!0,r.HandlebarsEnvironment=g;var t=e(4),f=e(5),a=n(f),i=e(9),l=e(29),h=e(31),v=n(h),P=e(32),H="4.7.7";r.VERSION=H;var C=8;r.COMPILER_REVISION=C;var E=7;r.LAST_COMPATIBLE_COMPILER_REVISION=E;var I={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};r.REVISION_CHANGES=I;var o="[object Object]";function g(y,p,R){this.helpers=y||{},this.partials=p||{},this.decorators=R||{},i.registerDefaultHelpers(this),l.registerDefaultDecorators(this)}g.prototype={constructor:g,logger:v.default,log:v.default.log,registerHelper:function(p,R){if(t.toString.call(p)===o){if(R)throw new a.default("Arg not supported with multiple helpers");t.extend(this.helpers,p)}else this.helpers[p]=R},unregisterHelper:function(p){delete this.helpers[p]},registerPartial:function(p,R){if(t.toString.call(p)===o)t.extend(this.partials,p);else{if(typeof R>"u")throw new a.default('Attempting to register a partial called "'+p+'" as undefined');this.partials[p]=R}},unregisterPartial:function(p){delete this.partials[p]},registerDecorator:function(p,R){if(t.toString.call(p)===o){if(R)throw new a.default("Arg not supported with multiple decorators");t.extend(this.decorators,p)}else this.decorators[p]=R},unregisterDecorator:function(p){delete this.decorators[p]},resetLoggedPropertyAccesses:function(){P.resetLoggedProperties()}};var w=v.default.log;r.log=w,r.createFrame=t.createFrame,r.logger=v.default},function(u,r){"use strict";r.__esModule=!0,r.extend=a,r.indexOf=v,r.escapeExpression=P,r.isEmpty=H,r.createFrame=C,r.blockParams=E,r.appendContextPath=I;var e={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`","=":"="},n=/[&<>"'`=]/g,t=/[&<>"'`=]/;function f(o){return e[o]}function a(o){for(var g=1;g0?(a.ids&&(a.ids=[a.name]),t.helpers.each(f,a)):i(this);if(a.data&&a.ids){var h=n.createFrame(a.data);h.contextPath=n.appendContextPath(a.data.contextPath,a.name),a={data:h}}return l(f,a)})},u.exports=r.default},function(u,r,e){(function(n){"use strict";var t=e(12).default,f=e(2).default;r.__esModule=!0;var a=e(4),i=e(5),l=f(i);r.default=function(h){h.registerHelper("each",function(v,P){if(!P)throw new l.default("Must pass iterator to #each");var H=P.fn,C=P.inverse,E=0,I="",o=void 0,g=void 0;P.data&&P.ids&&(g=a.appendContextPath(P.data.contextPath,P.ids[0])+"."),a.isFunction(v)&&(v=v.call(this)),P.data&&(o=a.createFrame(P.data));function w(b,F,c){o&&(o.key=b,o.index=F,o.first=F===0,o.last=!!c,g&&(o.contextPath=g+b)),I=I+H(v[b],{data:o,blockParams:a.blockParams([v[b],b],[g+b,null])})}if(v&&typeof v=="object")if(a.isArray(v))for(var y=v.length;E=0?a=i:a=parseInt(a,10)}return a},log:function(a){if(a=t.lookupLevel(a),typeof console<"u"&&t.lookupLevel(t.level)<=a){var i=t.methodMap[a];console[i]||(i="log");for(var l=arguments.length,h=Array(l>1?l-1:0),v=1;v=P.LAST_COMPATIBLE_COMPILER_REVISION&&O<=P.COMPILER_REVISION))if(O{(function(){var d=Handlebars.template,y=Handlebars.templates=Handlebars.templates||{};y["autocomplete-suggestions"]=d({1:function(e,l,a,p,u){var o,n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i="function",c=e.escapeExpression,t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return' +
+`+((o=t(a,"if").call(r,l!=null?t(l,"deprecated"):l,{name:"if",hash:{},fn:e.program(2,u,0),inverse:e.program(4,u,0),data:u,loc:{start:{line:16,column:10},end:{line:20,column:17}}}))!=null?o:"")+` +`+((o=t(a,"each").call(r,l!=null?t(l,"labels"):l,{name:"each",hash:{},fn:e.program(6,u,0),inverse:e.noop,data:u,loc:{start:{line:22,column:10},end:{line:24,column:19}}}))!=null?o:"")+`
+ +
+
+ +
+
+ +`+((o=t(a,"if").call(r,l!=null?t(l,"description"):l,{name:"if",hash:{},fn:e.program(8,u,0),inverse:e.noop,data:u,loc:{start:{line:39,column:8},end:{line:43,column:15}}}))!=null?o:"")+`
+`},2:function(e,l,a,p,u){var o,n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return' '+((o=(n=(n=r(a,"title")||(l!=null?r(l,"title"):l))!=null?n:e.hooks.helperMissing,typeof n=="function"?n.call(l??(e.nullContext||{}),{name:"title",hash:{},data:u,loc:{start:{line:17,column:49},end:{line:17,column:60}}}):n))!=null?o:"")+` +`},4:function(e,l,a,p,u){var o,n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return' '+((o=(n=(n=r(a,"title")||(l!=null?r(l,"title"):l))!=null?n:e.hooks.helperMissing,typeof n=="function"?n.call(l??(e.nullContext||{}),{name:"title",hash:{},data:u,loc:{start:{line:19,column:46},end:{line:19,column:57}}}):n))!=null?o:"")+` +`},6:function(e,l,a,p,u){return' '+e.escapeExpression(e.lambda(l,l))+` +`},8:function(e,l,a,p,u){var o,n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return`
+ `+((o=(n=(n=r(a,"description")||(l!=null?r(l,"description"):l))!=null?n:e.hooks.helperMissing,typeof n=="function"?n.call(l??(e.nullContext||{}),{name:"description",hash:{},data:u,loc:{start:{line:41,column:10},end:{line:41,column:27}}}):n))!=null?o:"")+` +
+`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n,r=l??(e.nullContext||{}),s=e.lookupProperty||function(i,c){if(Object.prototype.hasOwnProperty.call(i,c))return i[c]};return`
+
+
+
+ + Autocompletion results for "`+e.escapeExpression((n=(n=s(a,"term")||(l!=null?s(l,"term"):l))!=null?n:e.hooks.helperMissing,typeof n=="function"?n.call(r,{name:"term",hash:{},data:u,loc:{start:{line:6,column:55},end:{line:6,column:63}}}):n))+`" + + + Press RETURN for full-text search, TAB for previews + +
+
+`+((o=s(a,"each").call(r,l!=null?s(l,"suggestions"):l,{name:"each",hash:{},fn:e.program(1,u,0),inverse:e.noop,data:u,loc:{start:{line:13,column:6},end:{line:45,column:15}}}))!=null?o:"")+`
+
+
+`},useData:!0}),y["modal-layout"]=d({compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){return` +`},useData:!0}),y["quick-switch-modal-body"]=d({compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){return`
+ + +
+
+`},useData:!0}),y["quick-switch-results"]=d({1:function(e,l,a,p,u){var o,n=l??(e.nullContext||{}),r=e.hooks.helperMissing,s="function",i=e.escapeExpression,c=e.lookupProperty||function(t,f){if(Object.prototype.hasOwnProperty.call(t,f))return t[f]};return'
+ `+i((o=(o=c(a,"name")||(l!=null?c(l,"name"):l))!=null?o:r,typeof o===s?o.call(n,{name:"name",hash:{},data:u,loc:{start:{line:3,column:4},end:{line:3,column:12}}}):o))+` +
+`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return(o=n(a,"each").call(l??(e.nullContext||{}),l!=null?n(l,"results"):l,{name:"each",hash:{},fn:e.program(1,u,0),inverse:e.noop,data:u,loc:{start:{line:1,column:0},end:{line:5,column:9}}}))!=null?o:""},useData:!0}),y["search-results"]=d({1:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return" Search results for "+e.escapeExpression((o=(o=n(a,"value")||(l!=null?n(l,"value"):l))!=null?o:e.hooks.helperMissing,typeof o=="function"?o.call(l??(e.nullContext||{}),{name:"value",hash:{},data:u,loc:{start:{line:3,column:27},end:{line:3,column:36}}}):o))+` +`},3:function(e,l,a,p,u){return` Invalid search +`},5:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return(o=n(a,"each").call(l??(e.nullContext||{}),l!=null?n(l,"results"):l,{name:"each",hash:{},fn:e.program(6,u,0),inverse:e.noop,data:u,loc:{start:{line:10,column:2},end:{line:21,column:11}}}))!=null?o:""},6:function(e,l,a,p,u){var o,n=e.lambda,r=e.escapeExpression,s=e.lookupProperty||function(i,c){if(Object.prototype.hasOwnProperty.call(i,c))return i[c]};return`
+

+ + `+r(n(l!=null?s(l,"title"):l,l))+" ("+r(n(l!=null?s(l,"type"):l,l))+`) + +

+`+((o=s(a,"each").call(l??(e.nullContext||{}),l!=null?s(l,"excerpts"):l,{name:"each",hash:{},fn:e.program(7,u,0),inverse:e.noop,data:u,loc:{start:{line:17,column:8},end:{line:19,column:17}}}))!=null?o:"")+`
+`},7:function(e,l,a,p,u){var o;return'

'+((o=e.lambda(l,l))!=null?o:"")+`

+`},9:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return((o=(n(a,"isArray")||l&&n(l,"isArray")||e.hooks.helperMissing).call(l??(e.nullContext||{}),l!=null?n(l,"results"):l,{name:"isArray",hash:{},fn:e.program(10,u,0),inverse:e.program(12,u,0),data:u,loc:{start:{line:23,column:2},end:{line:29,column:14}}}))!=null?o:"")+` +

The search functionality is full-text based. Here are some tips:

+ +
    +
  • Multiple words (such as foo bar) are searched as OR
  • +
  • Use * anywhere (such as fo*) as wildcard
  • +
  • Use + before a word (such as +foo) to make its presence required
  • +
  • Use - before a word (such as -foo) to make its absence required
  • +
  • Use : to search on a particular field (such as field:word). The available fields are title, doc and type
  • +
  • Use WORD^NUMBER (such as foo^2) to boost the given word
  • +
  • Use WORD~NUMBER (such as foo~2) to do a search with edit distance on word
  • +
+ +

To quickly go to a module, type, or function, use the autocompletion feature in the sidebar search.

+`},10:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return"

Sorry, we couldn't find anything for "+e.escapeExpression((o=(o=n(a,"value")||(l!=null?n(l,"value"):l))!=null?o:e.hooks.helperMissing,typeof o=="function"?o.call(l??(e.nullContext||{}),{name:"value",hash:{},data:u,loc:{start:{line:24,column:48},end:{line:24,column:57}}}):o))+`.

+`},12:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return(o=n(a,"if").call(l??(e.nullContext||{}),l!=null?n(l,"value"):l,{name:"if",hash:{},fn:e.program(13,u,0),inverse:e.program(15,u,0),data:u,loc:{start:{line:25,column:2},end:{line:29,column:2}}}))!=null?o:""},13:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return"

Invalid search: "+e.escapeExpression((o=(o=n(a,"errorMessage")||(l!=null?n(l,"errorMessage"):l))!=null?o:e.hooks.helperMissing,typeof o=="function"?o.call(l??(e.nullContext||{}),{name:"errorMessage",hash:{},data:u,loc:{start:{line:26,column:23},end:{line:26,column:39}}}):o))+`.

+`},15:function(e,l,a,p,u){return`

Please type something into the search bar to perform a search.

+ `},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=l??(e.nullContext||{}),r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return`

+`+((o=r(a,"if").call(n,l!=null?r(l,"value"):l,{name:"if",hash:{},fn:e.program(1,u,0),inverse:e.program(3,u,0),data:u,loc:{start:{line:2,column:2},end:{line:6,column:9}}}))!=null?o:"")+`

+ +`+((o=(r(a,"isNonEmptyArray")||l&&r(l,"isNonEmptyArray")||e.hooks.helperMissing).call(n,l!=null?r(l,"results"):l,{name:"isNonEmptyArray",hash:{},fn:e.program(5,u,0),inverse:e.program(9,u,0),data:u,loc:{start:{line:9,column:0},end:{line:44,column:20}}}))!=null?o:"")},useData:!0}),y["settings-modal-body"]=d({1:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return(o=n(a,"if").call(l??(e.nullContext||{}),l!=null?n(l,"description"):l,{name:"if",hash:{},fn:e.program(2,u,0),inverse:e.noop,data:u,loc:{start:{line:40,column:6},end:{line:53,column:13}}}))!=null?o:""},2:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return`
+
+ `+e.escapeExpression(e.lambda(l!=null?n(l,"description"):l,l))+` +
+
+`+((o=n(a,"if").call(l??(e.nullContext||{}),l!=null?n(l,"displayAs"):l,{name:"if",hash:{},fn:e.program(3,u,0),inverse:e.program(5,u,0),data:u,loc:{start:{line:46,column:12},end:{line:50,column:19}}}))!=null?o:"")+`
+
+`},3:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return" "+((o=e.lambda(l!=null?n(l,"displayAs"):l,l))!=null?o:"")+` +`},5:function(e,l,a,p,u){var o=e.lookupProperty||function(n,r){if(Object.prototype.hasOwnProperty.call(n,r))return n[r]};return" "+e.escapeExpression(e.lambda(l!=null?o(l,"key"):l,l))+` +`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return`
+
+ + + + +
+ +
+`},useData:!0}),y["sidebar-items"]=d({1:function(e,l,a,p,u,o,n){var r,s=l??(e.nullContext||{}),i=e.hooks.helperMissing,c=e.lookupProperty||function(t,f){if(Object.prototype.hasOwnProperty.call(t,f))return t[f]};return((r=(c(a,"groupChanged")||l&&c(l,"groupChanged")||i).call(s,n[1],(r=o[0][0])!=null?c(r,"group"):r,{name:"groupChanged",hash:{},fn:e.program(2,u,0,o,n),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:2,column:2},end:{line:6,column:19}}}))!=null?r:"")+` +`+((r=(c(a,"nestingChanged")||l&&c(l,"nestingChanged")||i).call(s,n[1],o[0][0],{name:"nestingChanged",hash:{},fn:e.program(7,u,0,o,n),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:8,column:2},end:{line:10,column:21}}}))!=null?r:"")+` +
  • + +`+((r=c(a,"if").call(s,(r=o[0][0])!=null?c(r,"nested_title"):r,{name:"if",hash:{},fn:e.program(17,u,0,o,n),inverse:e.program(19,u,0,o,n),data:u,blockParams:o,loc:{start:{line:14,column:6},end:{line:18,column:13}}}))!=null?r:"")+` + +`+((r=(c(a,"isEmptyArray")||l&&c(l,"isEmptyArray")||i).call(s,(r=o[0][0])!=null?c(r,"headers"):r,{name:"isEmptyArray",hash:{},fn:e.program(3,u,0,o,n),inverse:e.program(21,u,0,o,n),data:u,blockParams:o,loc:{start:{line:21,column:4},end:{line:24,column:21}}}))!=null?r:"")+` +`+((r=(c(a,"isArray")||l&&c(l,"isArray")||i).call(s,(r=o[0][0])!=null?c(r,"headers"):r,{name:"isArray",hash:{},fn:e.program(24,u,0,o,n),inverse:e.program(28,u,0,o,n),data:u,blockParams:o,loc:{start:{line:26,column:4},end:{line:74,column:16}}}))!=null?r:"")+`
  • +`},2:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return'
  • + `+e.escapeExpression(e.lambda((n=o[1][0])!=null?r(n,"group"):n,l))+` +
  • +`},3:function(e,l,a,p,u){return""},5:function(e,l,a,p,u){return'translate="no"'},7:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return' +`},9:function(e,l,a,p,u){return"current-page open"},11:function(e,l,a,p,u){return"#content"},13:function(e,l,a,p,u){return"page"},15:function(e,l,a,p,u){return"false"},17:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return" "+((n=e.lambda((n=o[1][0])!=null?r(n,"nested_title"):n,l))!=null?n:"")+` +`},19:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return" "+((n=e.lambda((n=o[1][0])!=null?r(n,"title"):n,l))!=null?n:"")+` +`},21:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return' +`},22:function(e,l,a,p,u){return"true"},24:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return(n=(r(a,"isNonEmptyArray")||l&&r(l,"isNonEmptyArray")||e.hooks.helperMissing).call(l??(e.nullContext||{}),(n=o[1][0])!=null?r(n,"headers"):n,{name:"isNonEmptyArray",hash:{},fn:e.program(25,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:27,column:6},end:{line:35,column:26}}}))!=null?n:""},25:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return'
      +`+((n=r(a,"each").call(l??(e.nullContext||{}),(n=o[2][0])!=null?r(n,"headers"):n,{name:"each",hash:{},fn:e.program(26,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:29,column:10},end:{line:33,column:19}}}))!=null?n:"")+`
    +`},26:function(e,l,a,p,u,o){var n,r,s=l??(e.nullContext||{}),i=e.hooks.helperMissing,c="function",t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return`
  • + '+((n=(r=(r=t(a,"id")||(l!=null?t(l,"id"):l))!=null?r:i,typeof r===c?r.call(s,{name:"id",hash:{},data:u,blockParams:o,loc:{start:{line:31,column:54},end:{line:31,column:62}}}):r))!=null?n:"")+` +
  • +`},28:function(e,l,a,p,u,o){var n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i=e.lookupProperty||function(c,t){if(Object.prototype.hasOwnProperty.call(c,t))return c[t]};return'
      +`+((n=(i(a,"showSections")||l&&i(l,"showSections")||s).call(r,o[1][0],{name:"showSections",hash:{},fn:e.program(29,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:38,column:8},end:{line:52,column:25}}}))!=null?n:"")+((n=(i(a,"showSummary")||l&&i(l,"showSummary")||s).call(r,o[1][0],{name:"showSummary",hash:{},fn:e.program(34,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:53,column:8},end:{line:57,column:24}}}))!=null?n:"")+((n=i(a,"each").call(r,(n=o[1][0])!=null?i(n,"nodeGroups"):n,{name:"each",hash:{},fn:e.program(36,u,1,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:58,column:8},end:{line:72,column:17}}}))!=null?n:"")+`
    +`},29:function(e,l,a,p,u,o){var n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i=e.lambda,c=e.escapeExpression,t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return'
  • + + Sections + + +
      +`+((n=t(a,"each").call(r,l!=null?t(l,"sections"):l,{name:"each",hash:{},fn:e.program(32,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:45,column:14},end:{line:49,column:23}}}))!=null?n:"")+`
    +
  • +`},30:function(e,l,a,p,u){return"open"},32:function(e,l,a,p,u,o){var n,r,s=e.escapeExpression,i=l??(e.nullContext||{}),c=e.hooks.helperMissing,t="function",f=e.lookupProperty||function(m,v){if(Object.prototype.hasOwnProperty.call(m,v))return m[v]};return`
  • + '+((n=(r=(r=f(a,"id")||(l!=null?f(l,"id"):l))!=null?r:c,typeof r===t?r.call(i,{name:"id",hash:{},data:u,blockParams:o,loc:{start:{line:47,column:56},end:{line:47,column:64}}}):r))!=null?n:"")+` +
  • +`},34:function(e,l,a,p,u,o){var n,r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return`
  • + Summary +
  • +`},36:function(e,l,a,p,u,o){var n,r=e.lambda,s=e.escapeExpression,i=e.lookupProperty||function(c,t){if(Object.prototype.hasOwnProperty.call(c,t))return c[t]};return`
  • + + `+s(r((n=o[0][0])!=null?i(n,"name"):n,l))+` + + +
      +`+((n=i(a,"each").call(l??(e.nullContext||{}),(n=o[0][0])!=null?i(n,"nodes"):n,{name:"each",hash:{},fn:e.program(37,u,0,o),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:65,column:14},end:{line:69,column:23}}}))!=null?n:"")+`
    +
  • +`},37:function(e,l,a,p,u,o){var n,r,s=e.escapeExpression,i=l??(e.nullContext||{}),c=e.hooks.helperMissing,t="function",f=e.lookupProperty||function(m,v){if(Object.prototype.hasOwnProperty.call(m,v))return m[v]};return`
  • + '+s((r=(r=f(a,"id")||(l!=null?f(l,"id"):l))!=null?r:c,typeof r===t?r.call(i,{name:"id",hash:{},data:u,blockParams:o,loc:{start:{line:67,column:89},end:{line:67,column:95}}}):r))+` +
  • +`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u,o,n){var r,s=e.lookupProperty||function(i,c){if(Object.prototype.hasOwnProperty.call(i,c))return i[c]};return(r=s(a,"each").call(l??(e.nullContext||{}),l!=null?s(l,"nodes"):l,{name:"each",hash:{},fn:e.program(1,u,2,o,n),inverse:e.noop,data:u,blockParams:o,loc:{start:{line:1,column:0},end:{line:76,column:9}}}))!=null?r:""},useData:!0,useDepths:!0,useBlockParams:!0}),y.tabset=d({1:function(e,l,a,p,u){var o,n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i="function",c=e.escapeExpression,t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return' +`},2:function(e,l,a,p,u){return"-1"},4:function(e,l,a,p,u){return"0"},6:function(e,l,a,p,u){return"false"},8:function(e,l,a,p,u){return"true"},10:function(e,l,a,p,u){var o,n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i="function",c=e.escapeExpression,t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return'
    +`+((o=t(a,"each").call(r,l!=null?t(l,"content"):l,{name:"each",hash:{},fn:e.program(13,u,0),inverse:e.noop,data:u,loc:{start:{line:16,column:4},end:{line:18,column:13}}}))!=null?o:"")+`
    +`},11:function(e,l,a,p,u){return"hidden"},13:function(e,l,a,p,u){var o;return" "+((o=e.lambda(l,l))!=null?o:"")+` +`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=l??(e.nullContext||{}),r=e.lookupProperty||function(s,i){if(Object.prototype.hasOwnProperty.call(s,i))return s[i]};return`
    +`+((o=r(a,"each").call(n,l!=null?r(l,"tabs"):l,{name:"each",hash:{},fn:e.program(1,u,0),inverse:e.noop,data:u,loc:{start:{line:2,column:2},end:{line:9,column:11}}}))!=null?o:"")+`
    + +`+((o=r(a,"each").call(n,l!=null?r(l,"tabs"):l,{name:"each",hash:{},fn:e.program(10,u,0),inverse:e.noop,data:u,loc:{start:{line:12,column:0},end:{line:20,column:9}}}))!=null?o:"")},useData:!0}),y["tooltip-body"]=d({1:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return`
    + `+e.escapeExpression(e.lambda((o=l!=null?n(l,"hint"):l)!=null?n(o,"description"):o,l))+` +
    +`},3:function(e,l,a,p,u){var o,n=e.lambda,r=e.escapeExpression,s=e.lookupProperty||function(i,c){if(Object.prototype.hasOwnProperty.call(i,c))return i[c]};return`
    +

    + `+r(n((o=l!=null?s(l,"hint"):l)!=null?s(o,"title"):o,l))+` +
    `+r(n((o=l!=null?s(l,"hint"):l)!=null?s(o,"version"):o,l))+`
    +

    +
    +`+((o=s(a,"if").call(l??(e.nullContext||{}),(o=l!=null?s(l,"hint"):l)!=null?s(o,"description"):o,{name:"if",hash:{},fn:e.program(4,u,0),inverse:e.noop,data:u,loc:{start:{line:12,column:2},end:{line:16,column:9}}}))!=null?o:"")},4:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return`
    + `+((o=e.lambda((o=l!=null?n(l,"hint"):l)!=null?n(o,"description"):o,l))!=null?o:"")+` +
    +`},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return(o=n(a,"if").call(l??(e.nullContext||{}),l!=null?n(l,"isPlain"):l,{name:"if",hash:{},fn:e.program(1,u,0),inverse:e.program(3,u,0),data:u,loc:{start:{line:1,column:0},end:{line:17,column:7}}}))!=null?o:""},useData:!0}),y["tooltip-layout"]=d({compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){return`
    +
    +
    +`},useData:!0}),y["versions-dropdown"]=d({1:function(e,l,a,p,u){var o,n,r=l??(e.nullContext||{}),s=e.hooks.helperMissing,i="function",c=e.escapeExpression,t=e.lookupProperty||function(f,m){if(Object.prototype.hasOwnProperty.call(f,m))return f[m]};return' +`},2:function(e,l,a,p,u){return" selected disabled"},compiler:[8,">= 4.3.0"],main:function(e,l,a,p,u){var o,n=e.lookupProperty||function(r,s){if(Object.prototype.hasOwnProperty.call(r,s))return r[s]};return`
    + +
    +`},useData:!0})})();})(); diff --git a/doc/dist/html-PVRIOB7F.js b/doc/dist/html-PVRIOB7F.js new file mode 100644 index 0000000..178fef2 --- /dev/null +++ b/doc/dist/html-PVRIOB7F.js @@ -0,0 +1,56 @@ +(()=>{var ri=Object.create;var pt=Object.defineProperty;var si=Object.getOwnPropertyDescriptor;var oi=Object.getOwnPropertyNames;var ai=Object.getPrototypeOf,ci=Object.prototype.hasOwnProperty;var ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var li=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of oi(t))!ci.call(e,r)&&r!==n&&pt(e,r,{get:()=>t[r],enumerable:!(i=si(t,r))||i.enumerable});return e};var mt=(e,t,n)=>(n=e!=null?ri(ai(e)):{},li(t||!e||!e.__esModule?pt(n,"default",{value:e,enumerable:!0}):n,e));var At=ht((uo,Ct)=>{var It="Expected a function",_t=NaN,Ii="[object Symbol]",Ci=/^\s+|\s+$/g,Ai=/^[-+]0x[0-9a-f]+$/i,Pi=/^0b[01]+$/i,Ri=/^0o[0-7]+$/i,Ni=parseInt,Qi=typeof global=="object"&&global&&global.Object===Object&&global,Hi=typeof self=="object"&&self&&self.Object===Object&&self,Fi=Qi||Hi||Function("return this")(),Di=Object.prototype,Mi=Di.toString,Bi=Math.max,zi=Math.min,Fe=function(){return Fi.Date.now()};function $i(e,t,n){var i,r,s,o,a,l,u=0,f=!1,y=!1,g=!0;if(typeof e!="function")throw new TypeError(It);t=Ot(t)||0,ve(n)&&(f=!!n.leading,y="maxWait"in n,s=y?Bi(Ot(n.maxWait)||0,t):s,g="trailing"in n?!!n.trailing:g);function L(S){var C=i,D=r;return i=r=void 0,u=S,o=e.apply(D,C),o}function b(S){return u=S,a=setTimeout(h,t),f?L(S):o}function T(S){var C=S-l,D=S-u,q=t-C;return y?zi(q,s-D):q}function m(S){var C=S-l,D=S-u;return l===void 0||C>=t||C<0||y&&D>=s}function h(){var S=Fe();if(m(S))return k(S);a=setTimeout(h,T(S))}function k(S){return a=void 0,g&&i?L(S):(i=r=void 0,o)}function w(){a!==void 0&&clearTimeout(a),u=0,i=l=r=a=void 0}function Q(){return a===void 0?o:k(Fe())}function F(){var S=Fe(),C=m(S);if(i=arguments,r=this,l=S,C){if(a===void 0)return b(l);if(y)return a=setTimeout(h,t),L(l)}return a===void 0&&(a=setTimeout(h,t)),o}return F.cancel=w,F.flush=Q,F}function Vi(e,t,n){var i=!0,r=!0;if(typeof e!="function")throw new TypeError(It);return ve(n)&&(i="leading"in n?!!n.leading:i,r="trailing"in n?!!n.trailing:r),$i(e,t,{leading:i,maxWait:t,trailing:r})}function ve(e){var t=typeof e;return!!e&&(t=="object"||t=="function")}function qi(e){return!!e&&typeof e=="object"}function ji(e){return typeof e=="symbol"||qi(e)&&Mi.call(e)==Ii}function Ot(e){if(typeof e=="number")return e;if(ji(e))return _t;if(ve(e)){var t=typeof e.valueOf=="function"?e.valueOf():e;e=ve(t)?t+"":t}if(typeof e!="string")return e===0?e:+e;e=e.replace(Ci,"");var n=Pi.test(e);return n||Ri.test(e)?Ni(e.slice(2),n?2:8):Ai.test(e)?_t:+e}Ct.exports=Vi});var mn=ht((pn,hn)=>{(function(){var e=function(t){var n=new e.Builder;return n.pipeline.add(e.trimmer,e.stopWordFilter,e.stemmer),n.searchPipeline.add(e.stemmer),t.call(n,n),n.build()};e.version="2.3.9";e.utils={},e.utils.warn=function(t){return function(n){t.console&&console.warn&&console.warn(n)}}(this),e.utils.asString=function(t){return t==null?"":t.toString()},e.utils.clone=function(t){if(t==null)return t;for(var n=Object.create(null),i=Object.keys(t),r=0;r0){var f=e.utils.clone(n)||{};f.position=[a,u],f.index=s.length,s.push(new e.Token(i.slice(a,o),f))}a=o+1}}return s},e.tokenizer.separator=/[\s\-]+/;e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,n){n in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+n),t.label=n,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var n=t.label&&t.label in this.registeredFunctions;n||e.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,t)},e.Pipeline.load=function(t){var n=new e.Pipeline;return t.forEach(function(i){var r=e.Pipeline.registeredFunctions[i];if(r)n.add(r);else throw new Error("Cannot load unregistered function: "+i)}),n},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(n){e.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},e.Pipeline.prototype.after=function(t,n){e.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");i=i+1,this._stack.splice(i,0,n)},e.Pipeline.prototype.before=function(t,n){e.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},e.Pipeline.prototype.remove=function(t){var n=this._stack.indexOf(t);n!=-1&&this._stack.splice(n,1)},e.Pipeline.prototype.run=function(t){for(var n=this._stack.length,i=0;i1&&(ot&&(i=s),o!=t);)r=i-n,s=n+Math.floor(r/2),o=this.elements[s*2];if(o==t||o>t)return s*2;if(ol?f+=2:a==l&&(n+=i[u+1]*r[f+1],u+=2,f+=2);return n},e.Vector.prototype.similarity=function(t){return this.dot(t)/this.magnitude()||0},e.Vector.prototype.toArray=function(){for(var t=new Array(this.elements.length/2),n=1,i=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new e.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),r.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),r.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&r.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new e.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),r.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var f=s.str.charAt(0),y=s.str.charAt(1),g;y in s.node.edges?g=s.node.edges[y]:(g=new e.TokenSet,s.node.edges[y]=g),s.str.length==1&&(g.final=!0),r.push({node:g,editsRemaining:s.editsRemaining-1,str:f+s.str.slice(2)})}}}return i},e.TokenSet.fromString=function(t){for(var n=new e.TokenSet,i=n,r=0,s=t.length;r=t;n--){var i=this.uncheckedNodes[n],r=i.child.toString();r in this.minimizedNodes?i.parent.edges[i.char]=this.minimizedNodes[r]:(i.child._str=r,this.minimizedNodes[r]=i.child),this.uncheckedNodes.pop()}};e.Index=function(t){this.invertedIndex=t.invertedIndex,this.fieldVectors=t.fieldVectors,this.tokenSet=t.tokenSet,this.fields=t.fields,this.pipeline=t.pipeline},e.Index.prototype.search=function(t){return this.query(function(n){var i=new e.QueryParser(t,n);i.parse()})},e.Index.prototype.query=function(t){for(var n=new e.Query(this.fields),i=Object.create(null),r=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=t},e.Builder.prototype.k1=function(t){this._k1=t},e.Builder.prototype.add=function(t,n){var i=t[this._ref],r=Object.keys(this._fields);this._documents[i]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,n;do t=this.next(),n=t.charCodeAt(0);while(n>47&&n<58);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more())return e.QueryLexer.lexText},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var n=t.next();if(n==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){t.escapeCharacter();continue}if(n==":")return e.QueryLexer.lexField;if(n=="~")return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if(n=="^")return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if(n=="+"&&t.width()===1||n=="-"&&t.width()===1)return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if(n.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}},e.QueryParser=function(t,n){this.lexer=new e.QueryLexer(t),this.query=n,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseClause;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var t=this.peekLexeme();return this.lexemeIdx+=1,t},e.QueryParser.prototype.nextClause=function(){var t=this.currentClause;this.query.clause(t),this.currentClause={}},e.QueryParser.parseClause=function(t){var n=t.peekLexeme();if(n!=null)switch(n.type){case e.QueryLexer.PRESENCE:return e.QueryParser.parsePresence;case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(i+=" with value '"+n.str+"'"),new e.QueryParseError(i,n.start,n.end)}},e.QueryParser.parsePresence=function(t){var n=t.consumeLexeme();if(n!=null){switch(n.str){case"-":t.currentClause.presence=e.Query.presence.PROHIBITED;break;case"+":t.currentClause.presence=e.Query.presence.REQUIRED;break;default:var i="unrecognised presence operator'"+n.str+"'";throw new e.QueryParseError(i,n.start,n.end)}var r=t.peekLexeme();if(r==null){var i="expecting term or field, found nothing";throw new e.QueryParseError(i,n.start,n.end)}switch(r.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expecting term or field, found '"+r.type+"'";throw new e.QueryParseError(i,r.start,r.end)}}},e.QueryParser.parseField=function(t){var n=t.consumeLexeme();if(n!=null){if(t.query.allFields.indexOf(n.str)==-1){var i=t.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),r="unrecognised field '"+n.str+"', possible fields: "+i;throw new e.QueryParseError(r,n.start,n.end)}t.currentClause.fields=[n.str];var s=t.peekLexeme();if(s==null){var r="expecting term, found nothing";throw new e.QueryParseError(r,n.start,n.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var r="expecting term, found '"+s.type+"'";throw new e.QueryParseError(r,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var n=t.consumeLexeme();if(n!=null){t.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(i==null){t.nextClause();return}switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(r,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var n=t.consumeLexeme();if(n!=null){var i=parseInt(n.str,10);if(isNaN(i)){var r="edit distance must be numeric";throw new e.QueryParseError(r,n.start,n.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(s==null){t.nextClause();return}switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(r,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var n=t.consumeLexeme();if(n!=null){var i=parseInt(n.str,10);if(isNaN(i)){var r="boost must be numeric";throw new e.QueryParseError(r,n.start,n.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(s==null){t.nextClause();return}switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(r,s.start,s.end)}}},function(t,n){typeof define=="function"&&define.amd?define(n):typeof pn=="object"?hn.exports=n():t.lunr=n()}(this,function(){return e})})()});Handlebars.registerHelper("groupChanged",function(e,t,n){let i=t||"";if(e.group!==i)return delete e.nestedContext,e.group=i,n.fn(this)});Handlebars.registerHelper("nestingChanged",function(e,t,n){if(t.nested_context&&t.nested_context!==e.nestedContext){if(e.nestedContext=t.nested_context,e.lastModuleSeenInGroup!==t.nested_context)return n.fn(this)}else e.lastModuleSeenInGroup=t.title});Handlebars.registerHelper("showSections",function(e,t){if(e.sections.length>0)return t.fn(this)});Handlebars.registerHelper("showSummary",function(e,t){if(e.nodeGroups)return t.fn(this)});Handlebars.registerHelper("isArray",function(e,t){return Array.isArray(e)?t.fn(this):t.inverse(this)});Handlebars.registerHelper("isNonEmptyArray",function(e,t){return Array.isArray(e)&&e.length>0?t.fn(this):t.inverse(this)});Handlebars.registerHelper("isEmptyArray",function(e,t){return Array.isArray(e)&&e.length===0?t.fn(this):t.inverse(this)});Handlebars.registerHelper("isLocal",function(e,t){let n=window.location.pathname.split("/").pop();return n===e+".html"||n===e?t.fn(this):t.inverse(this)});var c=document.querySelector.bind(document),_=document.querySelectorAll.bind(document);function gt(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function me(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function $(){return document.body.dataset.type}function yt(e,t){if(e){for(let n of e){let i=n.nodeGroups&&n.nodeGroups.find(r=>r.nodes.some(s=>s.anchor===t));if(i)return i.key}return null}}function ge(e,t=!1){if(!e)return t?document.getElementById("top-content"):null;let n=document.getElementById(e);return n?n.matches(".detail")?n:["h1","h2","h3","h4","h5","h6"].includes(n.tagName.toLowerCase())?ui(n):null:null}function ui(e){let t=[e],n=e.nextElementSibling,i=e.tagName.toLowerCase();for(;n;){let s=n.tagName.toLowerCase();["h1","h2","h3","h4","h5","h6"].includes(s)&&s<=i?n=null:(t.push(n),n=n.nextElementSibling)}let r=document.createElement("div");return r.append(...t),r}function te(){return window.location.hash.replace(/^#/,"")}function vt(e){return new URLSearchParams(window.location.search).get(e)}function bt(e){return fetch(e).then(t=>t.ok).catch(()=>!1)}function St(e){document.readyState!=="loading"?e():document.addEventListener("DOMContentLoaded",e)}function ne(e){return!e||e.trim()===""}function xt(e,t){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>{n=null,e(...r)},t)}}function ye(){return document.head.querySelector("meta[name=project][content]").content}function ie(){return/(Macintosh|iPhone|iPad|iPod)/.test(window.navigator.userAgent)}var di="content",fi="tabs-open",pi="tabs-close",hi="H3",mi="tabset";function Lt(){gi().map(yi).forEach(n=>Si(n))}function gi(){let e=document.createNodeIterator(document.getElementById(di),NodeFilter.SHOW_COMMENT,{acceptNode(i){return i.nodeValue.trim()===fi?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}}),t=[],n;for(;n=e.nextNode();)t.push(n);return t}function yi(e,t,n){let i=[],r=[],s={label:"",content:[]};for(;e=e.nextSibling;){if(vi(e)){Et(s,r,t);break}i.push(e),e.nodeName===hi?(Et(s,r,t),s.label=e.innerText,s.content=[]):s.content.push(e.outerHTML)}let o=document.createElement("div");return o.className=mi,bi(i,o),o.innerHTML=Handlebars.templates.tabset({tabs:r}),o}function vi(e){return e.nodeName==="#comment"&&e.nodeValue.trim()===pi}function Et(e,t,n){if(e.label===""&&!e.content.length)return!1;let i=e.label,r=e.content;t.push({label:i,content:r,setIndex:n})}function bi(e,t){if(!e||!e.length)return!1;e[0].parentNode.insertBefore(t,e[0]),e.forEach(n=>t.appendChild(n))}function Si(e){let t={tabs:e.querySelectorAll(':scope [role="tab"]'),panels:e.querySelectorAll(':scope [role="tabpanel"]'),activeIndex:0};t.tabs.forEach((n,i)=>{n.addEventListener("click",r=>{G(i,t)}),n.addEventListener("keydown",r=>{let s=t.tabs.length-1;r.code==="ArrowLeft"?(r.preventDefault(),t.activeIndex===0?G(s,t):G(t.activeIndex-1,t)):r.code==="ArrowRight"?(r.preventDefault(),t.activeIndex===s?G(0,t):G(t.activeIndex+1,t)):r.code==="Home"?(r.preventDefault(),G(0,t)):r.code==="End"&&(r.preventDefault(),G(s,t))})})}function G(e,t){t.tabs[t.activeIndex].setAttribute("aria-selected","false"),t.tabs[t.activeIndex].tabIndex=-1,t.tabs[e].setAttribute("aria-selected","true"),t.tabs[e].tabIndex=0,t.tabs[e].focus(),t.panels[t.activeIndex].setAttribute("hidden",""),t.panels[t.activeIndex].tabIndex=-1,t.panels[e].removeAttribute("hidden"),t.panels[e].tabIndex=0,t.activeIndex=e}var Tt="ex_doc:settings",xi={tooltips:!0,theme:null,livebookUrl:null},He=class{constructor(){this._subscribers=[],this._settings=xi,this._loadSettings()}get(){return this._settings}update(t){let n=this._settings;this._settings={...this._settings,...t},this._subscribers.forEach(i=>i(this._settings,n)),this._storeSettings()}getAndSubscribe(t){this._subscribers.push(t),t(this._settings)}_loadSettings(){try{let t=localStorage.getItem(Tt);if(t){let n=JSON.parse(t);this._settings={...this._settings,...n}}this._loadSettingsLegacy()}catch(t){console.error(`Failed to load settings: ${t}`)}}_storeSettings(){try{this._storeSettingsLegacy(),localStorage.setItem(Tt,JSON.stringify(this._settings))}catch(t){console.error(`Failed to persist settings: ${t}`)}}_loadSettingsLegacy(){localStorage.getItem("tooltipsDisabled")!==null&&(this._settings={...this._settings,tooltips:!1}),localStorage.getItem("night-mode")==="true"&&(this._settings={...this._settings,nightMode:!0}),this._settings.nightMode===!0&&(this._settings={...this._settings,theme:"dark"})}_storeSettingsLegacy(){this._settings.tooltips?localStorage.removeItem("tooltipsDisabled"):localStorage.setItem("tooltipsDisabled","true"),this._settings.nightMode!==null?localStorage.setItem("night-mode",this._settings.nightMode===!0?"true":"false"):localStorage.removeItem("night-mode"),this._settings.theme!==null?(localStorage.setItem("night-mode",this._settings.theme==="dark"?"true":"false"),this._settings.nightMode=this._settings.theme==="dark"):(delete this._settings.nightMode,localStorage.removeItem("night-mode"))}},O=new He;var Ei=".content",wt=".content-inner",Li=".livebook-badge";function kt(e){e||wi(),ki(),Ti()}function Ti(){c(Ei).querySelectorAll("a").forEach(e=>{e.querySelector("code, img")&&e.classList.add("no-underline")})}function wi(){c(wt).setAttribute("tabindex",-1),c(wt).focus()}function ki(){let t=window.location.pathname.replace(/(\.html)?$/,".livemd"),n=new URL(t,window.location.href).toString();O.getAndSubscribe(i=>{let r=i.livebookUrl?Oi(i.livebookUrl,n):_i(n);for(let s of _(Li))s.href=r})}function _i(e){return`https://livebook.dev/run?url=${encodeURIComponent(e)}`}function Oi(e,t){return`${e}/import?url=${encodeURIComponent(t)}`}var Rt=mt(At());var Ui=768,De=300,re=".sidebar-toggle",Wi=".content",M={CLOSED:"closed",OPEN:"open",NO_PREF:"no_pref"},N={opened:"sidebar-opened",openingStart:"sidebar-opening-start",opening:"sidebar-opening",closed:"sidebar-closed",closingStart:"sidebar-closing-start",closing:"sidebar-closing"},Gi=Object.values(N),A={togglingTimeout:null,lastWindowWidth:window.innerWidth,sidebarPreference:M.NO_PREF};function Nt(){Qt(),Ki(),Yi()}function Ki(){let e=sessionStorage.getItem("sidebar_width");e&&Pt(e),new ResizeObserver(n=>{for(let i of n)Pt(i.contentRect.width)}).observe(document.getElementById("sidebar"))}function Pt(e){sessionStorage.setItem("sidebar_width",e),document.body.style.setProperty("--sidebarWidth",`${e}px`)}function Qt(){sessionStorage.getItem("sidebar_state")==="closed"||Ht()?(V(N.closed),c(re).setAttribute("aria-expanded","false")):(V(N.opened),c(re).setAttribute("aria-expanded","true")),setTimeout(()=>c(re).classList.add("sidebar-toggle--animated"),De)}function Ht(){return window.matchMedia(`screen and (max-width: ${Ui}px)`).matches}function V(...e){document.body.classList.remove(...Gi),document.body.classList.add(...e)}function Yi(){c(re).addEventListener("click",e=>{Me(),Zi()}),c(Wi).addEventListener("click",e=>{Xi()}),window.addEventListener("resize",(0,Rt.default)(e=>{Ji()},100))}function Me(){return Be()?Dt():ze()}function Be(){return document.body.classList.contains(N.opened)||document.body.classList.contains(N.opening)}function Ft(){return document.body.classList.contains(N.opened)}function ze(){return Mt(),sessionStorage.setItem("sidebar_state","opened"),c(re).setAttribute("aria-expanded","true"),new Promise((e,t)=>{requestAnimationFrame(()=>{V(N.openingStart),requestAnimationFrame(()=>{V(N.opening),A.togglingTimeout=setTimeout(()=>{V(N.opened),e()},De)})})})}function Dt(){return Mt(),sessionStorage.setItem("sidebar_state","closed"),c(re).setAttribute("aria-expanded","false"),new Promise((e,t)=>{requestAnimationFrame(()=>{V(N.closingStart),requestAnimationFrame(()=>{V(N.closing),A.togglingTimeout=setTimeout(()=>{V(N.closed),e()},De)})})})}function Mt(){A.togglingTimeout&&(clearTimeout(A.togglingTimeout),A.togglingTimeout=null)}function Ji(){A.lastWindowWidth!==window.innerWidth&&(A.lastWindowWidth=window.innerWidth,(A.sidebarPreference===M.OPEN||A.sidebarPreference===M.NO_PREF)&&Qt())}function Xi(){Ht()&&Be()&&Dt()}function Zi(){switch(A.sidebarPreference){case M.OPEN:A.sidebarPreference=M.CLOSED;break;case M.CLOSED:A.sidebarPreference=M.OPEN;break;case M.NO_PREF:Be()?A.sidebarPreference=M.OPEN:A.sidebarPreference=M.CLOSED}}function le(){return window.sidebarNodes||{}}function Bt(){return window.versionNodes||[]}var $e={search:"search",extras:"extras",modules:"modules",tasks:"tasks"},Ve=[$e.extras,$e.modules,$e.tasks],Se=e=>`#${e}-full-list`;function zt(){Ve.forEach(e=>{er(le(),e)}),be($()),Vt(),$t(),ar()}function er(e,t){let n=e[t]||[],i=c(Se(t));if(!i)return;let r=Handlebars.templates["sidebar-items"]({nodes:n,group:""});i.innerHTML=r,i.querySelectorAll("ul").forEach(s=>{if(s.innerHTML.trim()===""){let o=s.previousElementSibling;o.classList.contains("expand")&&o.classList.remove("expand"),s.remove()}}),i.querySelectorAll("li a + button").forEach(s=>{s.addEventListener("click",o=>{let l=o.target.closest("li");nr(l)})}),i.querySelectorAll("li a").forEach(s=>{s.addEventListener("click",o=>{let l=o.target.closest("li"),u=i.querySelector(".current-section");u&&rr(u),s.matches(".expand")&&(s.pathname===window.location.pathname||s.pathname===window.location.pathname+".html")&&qe(l)})})}function qe(e){e.classList.add("open"),e.querySelector("button[aria-controls]").setAttribute("aria-expanded","true")}function tr(e){e.classList.remove("open"),e.querySelector("button[aria-controls]").setAttribute("aria-expanded","false")}function nr(e){e.classList.contains("open")?tr(e):qe(e)}function ir(e){e.classList.add("current-section"),e.querySelector("a").setAttribute("aria-current","true")}function rr(e){e.classList.remove("current-section"),e.querySelector("a").setAttribute("aria-current","false")}function sr(e){e.classList.add("current-hash"),e.querySelector("a").setAttribute("aria-current","true")}function or(e){e.classList.remove("current-hash"),e.querySelector("a").setAttribute("aria-current","false")}function be(e){Ve.forEach(t=>{let n=c(`#${t}-list-tab-button`);if(n){let i=c(`#${n.getAttribute("aria-controls")}`);t===e?(n.parentElement.classList.add("selected"),n.setAttribute("aria-selected","true"),n.setAttribute("tabindex","0"),i.removeAttribute("hidden")):(n.parentElement.classList.remove("selected"),n.setAttribute("aria-selected","false"),n.setAttribute("tabindex","-1"),i.setAttribute("hidden","hidden"))}})}function $t(){let e=c(Se($()));if(!e)return;let t=e.querySelector("li.current-page");t&&(t.scrollIntoView(),e.scrollTop-=40)}function Vt(){let e=te()||"content",n=le()[$()]||[],i=yt(n,e),r=c(Se($()));if(!r)return;let s=r.querySelector(`li.current-page a.expand[href$="#${i}"]`);s&&qe(s.closest("li"));let o=r.querySelector(`li.current-page a[href$="#${e}"]`);if(o){let a=o.closest("ul");a.classList.contains("deflist")&&ir(a.closest("li")),sr(o.closest("li"))}}function ar(){Ve.forEach(t=>{let n=c(`#${t}-list-tab-button`);n&&n.addEventListener("click",i=>{be(t),$t()})});let e=c("#sidebar-listNav");e.addEventListener("keydown",t=>{if(t.key!=="ArrowRight"&&t.key!=="ArrowLeft")return;let n=Array.from(e.querySelectorAll('[role="tab"]')).map(r=>r.dataset.type),i=e.querySelector('[role="tab"][aria-selected="true"]').dataset.type;if(t.key==="ArrowRight"){let r=n.indexOf(i)+1;r>=n.length&&(r=0);let s=n[r];be(s),c(`#${s}-list-tab-button`).focus()}else if(t.key==="ArrowLeft"){let r=n.indexOf(i)-1;r<0&&(r=n.length-1);let s=n[r];be(s),c(`#${s}-list-tab-button`).focus()}}),window.addEventListener("hashchange",t=>{let n=c(Se($()));if(!n)return;let i=n.querySelector("li.current-page li.current-hash");i&&or(i),Vt()})}var B={module:"module",moduleChild:"module-child",mixTask:"mix-task",extra:"extra",section:"section"};function jt(e,t=8){if(ne(e))return[];let n=le(),i=[...je(n.modules,e,B.module,"module"),...cr(n.modules,e,B.moduleChild),...je(n.tasks,e,B.mixTask,"mix task"),...je(n.extras,e,B.extra,"page"),...Ue(n.modules,e,B.section,"module"),...Ue(n.tasks,e,B.section,"mix task"),...Ue(n.extras,e,B.section,"page")].filter(r=>r!==null);return mr(i).slice(0,t)}function je(e,t,n,i){return e.map(r=>ur(r,t,n,i))}function cr(e,t,n){return e.filter(i=>i.nodeGroups).flatMap(i=>i.nodeGroups.flatMap(({key:r,nodes:s})=>{let o=hr(r);return s.map(a=>dr(a,i.id,t,n,o)||pr(a,i.id,t,n,o))}))}function Ue(e,t,n,i){return e.flatMap(r=>lr(r).map(s=>fr(r,s,t,n,i)))}function lr(e){return(e.sections||[]).concat(e.headers||[])}function ur(e,t,n,i){return Ee(e.title,t)?{link:`${e.id}.html`,title:we(e.title,t),description:null,matchQuality:Le(e.title,t),deprecated:e.deprecated,labels:[i],category:n}:null}function dr(e,t,n,i,r){return Ee(e.id,n)?{link:`${t}.html#${e.anchor}`,title:we(e.id,n),labels:[r],description:t,matchQuality:Le(e.id,n),deprecated:e.deprecated,category:i}:null}function fr(e,t,n,i,r){return Ut(t.id,n)?{link:`${e.id}.html#${t.anchor}`,title:we(t.id,n),description:e.title,matchQuality:Le(t.id,n),labels:[r,"section"],category:i}:null}function pr(e,t,n,i,r){let s=`${t}.${e.id}`,o=`${t}:${e.id}`,a,l;if(Ee(s,n))a=s,l=/\./g;else if(Ee(o,n))a=o,l=/:/g;else return null;let u=n.replace(l," ");return Ut(e.id,u)?{link:`${t}.html#${e.anchor}`,title:we(e.id,u),label:r,description:t,matchQuality:Le(a,n),deprecated:e.deprecated,category:i}:null}function hr(e){switch(e){case"callbacks":return"callback";case"types":return"type";default:return"function"}}function mr(e){return e.slice().sort((t,n)=>t.matchQuality!==n.matchQuality?n.matchQuality-t.matchQuality:qt(t.category)-qt(n.category))}function qt(e){switch(e){case B.module:return 1;case B.moduleChild:return 2;case B.mixTask:return 3;default:return 4}}function Ut(e,t){return Te(t).some(i=>Wt(e,i))}function Ee(e,t){return Te(t).every(i=>Wt(e,i))}function Wt(e,t){return e.toLowerCase().includes(t.toLowerCase())}function Le(e,t){let n=Te(t),r=n.map(o=>o.length).reduce((o,a)=>o+a,0)/e.length,s=gr(e,n[0])?1:0;return r+s}function gr(e,t){return e.toLowerCase().startsWith(t.toLowerCase())}function Te(e){return e.trim().split(/\s+/)}function we(e,t){let n=Te(t).sort((i,r)=>r.length-i.length);return xe(e,n)}function xe(e,t){if(t.length===0)return e;let[n,...i]=t,r=e.match(new RegExp(`(.*)(${gt(n)})(.*)`,"i"));if(r){let[,s,o,a]=r;return xe(s,t)+""+me(o)+""+xe(a,t)}else return xe(e,i)}var ke=null,K=null;function Gt(){K=document.getElementById("toast"),K.addEventListener("click",e=>{clearTimeout(ke),e.target.classList.remove("show")})}function We(e){K&&(clearTimeout(ke),K.innerText=e,K.classList.add("show"),ke=setTimeout(()=>{K.classList.remove("show"),ke=setTimeout(function(){K.innerText=""},1e3)},5e3))}var Kt="dark",Ge=["system","dark","light"];function Yt(e){O.getAndSubscribe(t=>{document.body.classList.toggle(Kt,Xt(e||t.theme))}),vr()}function Jt(){let e=Ge[Ge.indexOf(Ke())+1]||Ge[0];O.update({theme:e}),We(`Set theme to "${e}"`)}function Ke(){return O.get().theme||"system"}function Xt(e){return e==="dark"||yr()&&(e==null||e==="system")}function yr(){return window.matchMedia("(prefers-color-scheme: dark)").matches}function vr(){window.matchMedia("(prefers-color-scheme: dark)").addListener(e=>{let t=O.get().theme,n=Xt(t);(t==null||t==="system")&&(document.body.classList.toggle(Kt,n),We(`Browser changed theme to "${n?"dark":"light"}"`))})}var se=".autocomplete",Oe=".autocomplete-suggestions",_e=".autocomplete-suggestion",I={autocompleteSuggestions:[],previewOpen:!1,selectedIdx:-1};function br(){c(se).classList.add("shown")}function Ye(){c(se).classList.remove("shown")}function Zt(){return c(se).classList.contains("shown")}function Je(e){I.autocompleteSuggestions=jt(e),I.selectedIdx=-1,ne(e)?Ye():(Sr({term:e,suggestions:I.autocompleteSuggestions}),Ie(0),br())}function Sr({term:e,suggestions:t}){let n=Handlebars.templates["autocomplete-suggestions"]({suggestions:t,term:e}),i=c(se);i.innerHTML=n}function en(){return I.selectedIdx===-1?null:I.autocompleteSuggestions[I.selectedIdx]}function Ie(e){nn(xr(e))}function tn(e){if(e.data.type==="preview"){let{contentHeight:t}=e.data,n=c(".autocomplete-preview");n&&(n.style.height=`${t+32}px`,n.classList.remove("loading"))}}function nn(e){I.selectedIdx=e;let t=c(Oe),n=c(`${_e}.selected`),i=c(`${_e}[data-index="${I.selectedIdx}"]`);if(n&&n.classList.remove("selected"),i){if(I.previewOpen){sn(),window.addEventListener("message",tn),t.classList.add("previewing");let r=document.createElement("div");r.classList.add("autocomplete-preview"),r.classList.add("loading");let s=i.href.replace(".html",`.html?preview=true&theme=${Ke()}`),o=document.createElement("iframe");o.setAttribute("src",s),r.appendChild(document.createElement("div")),r.appendChild(document.createElement("span")),r.appendChild(o),i.parentNode.insertBefore(r,i.nextSibling)}i.classList.add("selected"),i.scrollIntoView({block:"nearest"})}else t&&(t.scrollTop=0)}function rn(){I.previewOpen?Ce():Xe()}function Ce(){I.previewOpen=!1;let e=c(Oe);e&&e.classList.remove("previewing"),sn()}function Xe(e){I.previewOpen=!0,e?e=e.closest(_e):e=c(`${_e}[data-index="${I.selectedIdx}"]`),e&&nn(parseInt(e.dataset.index))}function sn(){let e=c(".autocomplete-preview");e&&(e.remove(),window.removeEventListener("message",tn))}function xr(e){let t=I.autocompleteSuggestions.length+1;return(I.selectedIdx+e+1+t)%t-1}var ue="form.search-bar input",Er="form.search-bar .search-close-button";function cn(){Lr(),window.onTogglePreviewClick=function(e,t){e.preventDefault(),e.stopImmediatePropagation(),et(),t?Xe(e.target):Ce()}}function ln(e){let t=c(ue);t.value=e}function et(){let e=c(ue);document.body.classList.add("search-focused"),e.focus()}function Lr(){let e=c(ue);if(document.querySelector('meta[name="exdoc:autocomplete"][content="off"]'))return e.addEventListener("keydown",t=>{t.key==="Enter"&&on(t)}),!0;e.addEventListener("keydown",t=>{let n=ie();t.key==="Escape"?(Ae(),e.blur()):t.key==="Enter"?on(t):t.key==="ArrowUp"||n&&t.ctrlKey&&t.key==="p"?(Ie(-1),t.preventDefault()):t.key==="ArrowDown"||n&&t.ctrlKey&&t.key==="n"?(Ie(1),t.preventDefault()):t.key==="Tab"&&(rn(),t.preventDefault())}),e.addEventListener("input",t=>{Je(t.target.value)}),e.addEventListener("focus",t=>{document.body.classList.contains("search-focused")||(document.body.classList.add("search-focused"),Je(t.target.value))}),e.addEventListener("blur",t=>{let n=t.relatedTarget,i=c(Oe);if(n&&i&&i.contains(n))return setTimeout(()=>{Zt()&&e.focus()},1e3),null;Pe()}),c(se).addEventListener("click",t=>{t.shiftKey||t.ctrlKey?e.focus():(Ae(),Pe())}),c(Er).addEventListener("click",t=>{Ae(),Pe()})}function on(e){let t=c(ue),n=e.shiftKey||e.ctrlKey,i=en();e.preventDefault();let r=n?"_blank":"_self",s=document.createElement("a");if(s.setAttribute("target",r),i)s.setAttribute("href",i.link);else{let o=document.querySelector('meta[name="exdoc:full-text-search-url"]'),a=o?o.getAttribute("content"):"search.html?q=";s.setAttribute("href",`${a}${encodeURIComponent(t.value)}`)}s.click(),n||(Ae(),Pe())}function Ae(){let e=c(ue);e.value=""}function Pe(){Ce(),document.body.classList.remove("search-focused"),Ye()}var Ze=window.scrollY,Tr=70,an=-2;window.addEventListener("scroll",function(){let e=window.scrollY;e===0||Ze-eTr?document.body.classList.remove("scroll-sticky"):Ze-e>Math.abs(an)&&document.body.classList.add("scroll-sticky"),Ze=e<=0?0:e},!1);var un=".sidebar-projectVersion",dn=".sidebar-projectVersionsDropdown";function fn(){let e=Bt();if(e.length>0){let n=c(un).textContent.trim(),i=kr(e,n);wr({nodes:i})}}function wr({nodes:e}){let t=c(un),n=Handlebars.templates["versions-dropdown"]({nodes:e});t.innerHTML=n,c(dn).addEventListener("change",Or)}function kr(e,t){return _r(e,t).map(i=>({...i,isCurrentVersion:i.version===t}))}function _r(e,t){return e.some(i=>i.version===t)?e:[{version:t,url:"#"},...e]}function Or(e){let t=e.target.value,n=window.location.pathname.split("/").pop()+window.location.hash,i=`${t}/${n}`;bt(i).then(r=>{r?window.location.href=i:window.location.href=t})}function tt(){let e=c(dn);e&&(e.focus(),e.addEventListener("keydown",t=>{(t.key==="Escape"||t.key==="v")&&(t.preventDefault(),e.blur())}),navigator.userActivation.isActive&&"showPicker"in HTMLSelectElement.prototype&&e.showPicker())}var H=mt(mn());var Re=80,Ir="#search";function yn(){let e=window.location.pathname;if(e.endsWith("/search.html")||e.endsWith("/search")){let t=vt("q");Cr(t)}}async function Cr(e){if(ne(e))nt({value:e});else{ln(e);let t=await Ar();try{let n=e.replaceAll(/(\B|\\):/g,"\\:"),i=zr(t.search(n));nt({value:e,results:i})}catch(n){nt({value:e,errorMessage:n.message})}}}function nt({value:e,results:t,errorMessage:n}){let i=c(Ir),r=Handlebars.templates["search-results"]({value:e,results:t,errorMessage:n});i.innerHTML=r}async function Ar(){H.default.tokenizer.separator=/\s+/,H.default.QueryLexer.termSeparator=/\s+/,H.default.Pipeline.registerFunction(bn,"docTokenSplitter"),H.default.Pipeline.registerFunction(Sn,"docTrimmer");let e=await Pr();if(e)return e;let t=Dr();return Rr(t),t}async function Pr(){try{let e=sessionStorage.getItem(vn());if(e){let t=await Qr(e);return H.default.Index.load(t)}else return null}catch(e){return console.error("Failed to load index: ",e),null}}async function Rr(e){try{let t=await Nr(e);sessionStorage.setItem(vn(),t)}catch(t){console.error("Failed to save index: ",t)}}async function Nr(e){let t=new Blob([JSON.stringify(e)],{type:"application/json"}).stream().pipeThrough(new window.CompressionStream("gzip")),i=await(await new Response(t).blob()).arrayBuffer();return Hr(i)}async function Qr(e){let t=new Blob([Fr(e)],{type:"application/json"}).stream().pipeThrough(new window.DecompressionStream("gzip")),n=await new Response(t).text();return JSON.parse(n)}function Hr(e){let t="",n=new Uint8Array(e),i=n.byteLength;for(let r=0;r{this.add(e)})})}function Mr(e){e.pipeline.before(H.default.stemmer,bn)}function bn(e){let t=[e],n=/\/\d+$/,i=/\:|\./,r=e.toString();if(r.startsWith("`")&&r.endsWith("`")&&(r=r.slice(1,-1),t.push(e.clone().update(()=>r))),n.test(r)){let o=e.toString().replace(n,"");t.push(e.clone().update(()=>o));let a=o.split(i);if(a.length>1){for(let u of a)t.push(e.clone().update(()=>u));let l=e.toString().split(i);t.push(e.clone().update(()=>l[l.length-1]))}r=a[a.length-1]}else r.startsWith("@")?(r=r.substring(1),t.push(e.clone().update(()=>r))):r.startsWith(":")&&(r=r.substring(1),t.push(e.clone().update(()=>r)));let s=r.split(/\_|\-/);if(s.length>1)for(let o of s)t.push(e.clone().update(()=>o));return t}function Br(e){e.pipeline.before(H.default.stemmer,Sn)}function Sn(e){return e.update(function(t){return t.replace(/^[^@:\w]+/,"").replace(/[^\?\!\w]+$/,"")})}function zr(e){return e.filter(t=>gn(t.ref)).map(t=>{let n=gn(t.ref),i=t.matchData.metadata;return{...n,metadata:i,excerpts:$r(n,i)}})}function gn(e){return searchData.items.find(t=>t.ref===e)||null}function $r(e,t){let{doc:n}=e,r=Object.keys(t).filter(s=>"doc"in t[s]).map(s=>t[s].doc.position.map(([o,a])=>Vr(n,o,a))).reduce((s,o)=>s.concat(o),[]);return r.length===0?[n.slice(0,Re*2)+(Re*20?"...":"",e.slice(i,t),""+me(e.slice(t,t+n))+"",e.slice(t+n,r),r{let n=t.getAttribute("data-group-id");t.addEventListener("mouseenter",i=>{xn(n,!0)}),t.addEventListener("mouseleave",i=>{xn(n,!1)})})}function xn(e,t){_(`[data-group-id="${e}"]`).forEach(i=>{i.classList.toggle(qr,t)})}var J=".modal",Ur=".modal .modal-close",Wr=".modal .modal-title",Gr=".modal .modal-body",Ln='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',z={prevFocus:null,lastFocus:null,ignoreFocusChanges:!1};function Tn(){Kr()}function Kr(){let e=Handlebars.templates["modal-layout"]();document.body.insertAdjacentHTML("beforeend",e),c(J).addEventListener("keydown",t=>{t.key==="Escape"&&Y()}),c(Ur).addEventListener("click",t=>{Y()}),c(J).addEventListener("click",t=>{t.target.classList.contains("modal")&&Y()})}function wn(e){if(z.ignoreFocusChanges)return;let t=c(J);if(t.contains(e.target))z.lastFocus=e.target;else{z.ignoreFocusChanges=!0;let n=Yr(t);z.lastFocus===n?Jr(t).focus():n.focus(),z.ignoreFocusChanges=!1,z.lastFocus=document.activeElement}}function Yr(e){return e.querySelector(Ln)}function Jr(e){let t=e.querySelectorAll(Ln);return t[t.length-1]}function Ne({title:e,body:t}){z.prevFocus=document.activeElement,document.addEventListener("focus",wn,!0),c(Wr).innerHTML=e,c(Gr).innerHTML=t,c(J).classList.add("shown"),c(J).focus()}function Y(){c(J).classList.remove("shown"),document.addEventListener("focus",wn,!0),z.prevFocus&&z.prevFocus.focus(),z.prevFocus=null}function kn(){return c(J).classList.contains("shown")}var Xr="https://hexdocs.pm/%%",Zr="https://www.erlang.org/doc/apps/%%",es="https://hex.pm/api/packages?search=name:%%*",ts=".display-quick-switch",it="#quick-switch-input",On="#quick-switch-results",ns=".quick-switch-result",is=300,rs=9,In=["erts","asn1","common_test","compiler","crypto","debugger","dialyzer","diameter","edoc","eldap","erl_interface","et","eunit","ftp","inets","jinterface","kernel","megaco","mnesia","observer","odbc","os_mon","parsetools","public_key","reltool","runtime_tools","sasl","snmp","ssh","ssl","stdlib","syntax_tools","tftp","tools","wx","xmerl"],ss=["elixir","eex","ex_unit","hex","iex","logger","mix"].concat(In).map(e=>({name:e})),Cn=2,P={autocompleteResults:[],selectedIdx:null};function An(){os()}function os(){_(ts).forEach(e=>{e.addEventListener("click",t=>{st()})})}function as(e){if(e.key==="Enter"){let t=e.target.value;ls(t),e.preventDefault()}else e.key==="ArrowUp"?(_n(-1),e.preventDefault()):e.key==="ArrowDown"&&(_n(1),e.preventDefault())}function cs(e){let t=e.target.value;if(t.lengthn.json()).then(n=>{Array.isArray(n)&&(P.autocompleteResults=ps(e,n),P.selectedIdx=null,c(it).value.length>=Cn&&fs({results:P.autocompleteResults}))})}function fs({results:e}){let t=c(On),n=Handlebars.templates["quick-switch-results"]({results:e});t.innerHTML=n,_(ns).forEach(i=>{i.addEventListener("click",r=>{let s=i.getAttribute("data-index"),o=P.autocompleteResults[s];rt(o.name)})})}function ps(e,t){return ss.concat(t).filter(n=>n.name.toLowerCase().includes(e.toLowerCase())).filter(n=>n.releases===void 0||n.releases[0].has_docs===!0).slice(0,rs)}function _n(e){P.selectedIdx=hs(e);let t=c(".quick-switch-result.selected"),n=c(`.quick-switch-result[data-index="${P.selectedIdx}"]`);t&&t.classList.remove("selected"),n&&n.classList.add("selected")}function hs(e){let t=P.autocompleteResults.length;if(P.selectedIdx===null){if(e>=0)return 0;if(e<0)return t-1}return(P.selectedIdx+e+t)%t}var ms=".display-settings",gs="#settings-modal-content",ot="#modal-settings-tab",at="#modal-keyboard-shortcuts-tab",Rn="#settings-content",Nn="#keyboard-shortcuts-content",ys=[{title:"Settings",id:"modal-settings-tab"},{title:"Keyboard shortcuts",id:"modal-keyboard-shortcuts-tab"}];function Qn(){vs()}function vs(){_(ms).forEach(e=>{e.addEventListener("click",t=>{ct()})})}function Pn(){c(at).classList.remove("active"),c(ot).classList.add("active"),c(Rn).classList.remove("hidden"),c(Nn).classList.add("hidden")}function bs(){c(at).classList.add("active"),c(ot).classList.remove("active"),c(Nn).classList.remove("hidden"),c(Rn).classList.add("hidden")}function ct(){Ne({title:ys.map(({id:s,title:o})=>``).join(""),body:Handlebars.templates["settings-modal-body"]({shortcuts:lt})});let e=c(gs),t=e.querySelector('[name="theme"]'),n=e.querySelector('[name="tooltips"]'),i=e.querySelector('[name="direct_livebook_url"]'),r=e.querySelector('[name="livebook_url"]');O.getAndSubscribe(s=>{t.value=s.theme||"system",n.checked=s.tooltips,s.livebookUrl===null?(i.checked=!1,r.classList.add("hidden"),r.tabIndex=-1):(i.checked=!0,r.classList.remove("hidden"),r.tabIndex=0,r.value=s.livebookUrl)}),t.addEventListener("change",s=>{O.update({theme:s.target.value})}),n.addEventListener("change",s=>{O.update({tooltips:s.target.checked})}),i.addEventListener("change",s=>{let o=s.target.checked?r.value:null;O.update({livebookUrl:o})}),r.addEventListener("input",s=>{O.update({livebookUrl:s.target.value})}),c(ot).addEventListener("click",s=>{Pn()}),c(at).addEventListener("click",s=>{bs()}),Pn()}var Ss="#settings-modal-content",lt=[{key:"c",description:"Toggle sidebar",action:Me},{key:"n",description:"Cycle themes",action:Jt},{key:"s",description:"Focus search bar",displayAs:"/ or s",action:ut},{key:"/",action:ut},{key:"k",hasModifier:!0,action:ut},{key:"v",description:"Open/focus version select",action:Ts},{key:"g",description:"Go to package docs",displayAs:"g",action:st},{key:"?",displayAs:"?",description:"Bring up this modal",action:ws}],dt={shortcutBeingPressed:null};function Hn(){xs()}function xs(){document.addEventListener("keydown",Es),document.addEventListener("keyup",Ls)}function Es(e){if(dt.shortcutBeingPressed||e.target.matches("input, select, textarea"))return;let t=lt.find(n=>n.hasModifier?ie()&&e.metaKey||e.ctrlKey?n.key===e.key:!1:e.ctrlKey||e.metaKey||e.altKey?!1:n.key===e.key);t&&(dt.shortcutBeingPressed=t,e.preventDefault(),t.action(e))}function Ls(e){dt.shortcutBeingPressed=null}function ut(e){Y(),et()}function Ts(){Y(),Ft()?tt():ze().then(tt)}function ws(){ks()?Y():ct()}function ks(){return kn()&&c(Ss)}var X={plain:"plain",function:"function",module:"module"},_s=[{href:"typespecs.html#basic-types",hint:{kind:X.plain,description:"Basic type"}},{href:"typespecs.html#literals",hint:{kind:X.plain,description:"Literal"}},{href:"typespecs.html#built-in-types",hint:{kind:X.plain,description:"Built-in type"}}],Qe={cancelHintFetching:null};function Fn(e){if(Mn(e))return!0;let t=/#.*\//;return e.includes("#")&&!t.test(e)?!1:e.includes(".html")}function Dn(e){let t=Mn(e);return t?Promise.resolve(t):Os(e)}function Mn(e){let t=_s.find(n=>e.includes(n.href));return t?t.hint:null}function Os(e){let t=e.replace(".html",".html?hint=true");return new Promise((n,i)=>{let r=document.createElement("iframe");r.setAttribute("src",t),r.style.display="none";function s(a){let{href:l,hint:u}=a.data;t===l&&(o(),n(u))}Qe.cancelHintFetching=()=>{o(),i(new Error("cancelled"))};function o(){r.remove(),window.removeEventListener("message",s),Qe.cancelHintFetching=null}window.addEventListener("message",s),document.body.appendChild(r)})}function Bn(){Qe.cancelHintFetching&&Qe.cancelHintFetching()}function zn(e){let n=e.querySelector("h1").textContent,i=e.querySelector(".docstring > p"),r=i?i.innerHTML:"";return{kind:X.function,title:n.trim(),description:r.trim()}}function $n(e){let n=e.querySelector("h1 > span").textContent,i=e.querySelector("#moduledoc p"),r=i?i.innerHTML:"";return{kind:X.module,title:n.trim(),description:r.trim()}}var Is=".content a",ft=".tooltip",Cs=".tooltip .tooltip-body",qn="body .content-inner",As="#content",jn="tooltip-shown",de=10,Ps=de*4,Vn={height:450,width:768},Rs=100,oe={currentLinkElement:null,hoverDelayTimeout:null};function Un(){Ns(),Qs()}function Ns(){let e=Handlebars.templates["tooltip-layout"]();c(qn).insertAdjacentHTML("beforeend",e)}function Qs(){_(Is).forEach(e=>{Hs(e)&&(e.addEventListener("mouseenter",t=>{Ds(e)}),e.addEventListener("mouseleave",t=>{$s(e)}))})}function Hs(e){return!(e.getAttribute("data-no-tooltip")!==null||Fs(e.href)||!Fn(e.href))}function Fs(e){let t=e.replace(As,"");return window.location.href.split("#")[0]===t}function Ds(e){Ms()&&(oe.currentLinkElement=e,oe.hoverDelayTimeout=setTimeout(()=>{Dn(e.href).then(t=>{Bs(t),zs()}).catch(()=>{})},Rs))}function Ms(){let e=window.innerWidthe.firstElementChild&&e.firstElementChild.tagName==="CODE").forEach(e=>e.insertAdjacentHTML("beforeend",Js)),Array.from(_(".copy-button")).forEach(e=>{let t;e.addEventListener("click",()=>{let n=e.querySelector("[aria-live]");t&&clearTimeout(t);let i=Array.from(e.parentElement.querySelector("code").childNodes).filter(r=>!(r.tagName==="SPAN"&&r.classList.contains("unselectable"))).map(r=>r.textContent).join("");navigator.clipboard.writeText(i),e.classList.add("clicked"),n.innerHTML="Copied! ✓",t=setTimeout(()=>{e.classList.remove("clicked"),n.innerHTML=""},3e3)})})}function Jn(){let e=ie()?"apple-os":"non-apple-os";document.documentElement.classList.add(e)}function Zn(){let e=ge(te(),!0);e&&Zs(e)}function Zs(e){no(e),eo(),to(),Xn(),window.addEventListener("resize",t=>{Xn()})}function Xn(){let e=document.body.scrollHeight,t=document.getElementById("content").parentElement.offsetHeight,n={type:"preview",maxHeight:e,contentHeight:t};window.parent.postMessage(n,"*")}function eo(){let e=document.getElementsByTagName("a");for(let t of e)t.getAttribute("target")!=="_blank"&&t.setAttribute("target","_parent")}function to(){window.scrollTo(0,0)}function no(e){document.body.classList.add("preview");let t=document.getElementById("content");t.innerHTML=e.innerHTML}St(()=>{let e=new URLSearchParams(window.location.search),t=e.has("preview");Lt(),Yt(e.get("theme")),kt(t),En(),Un(),Kn(),Yn(),Jn(),t?Zn():(fn(),Nt(),zt(),cn(),Tn(),Hn(),An(),Gt(),yn(),Qn())});})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/doc/dist/html-erlang-4IXSOGMD.css b/doc/dist/html-erlang-4IXSOGMD.css new file mode 100644 index 0000000..6339eb0 --- /dev/null +++ b/doc/dist/html-erlang-4IXSOGMD.css @@ -0,0 +1,6 @@ +:root{--main: hsl(0, 100%, 44%);--mainDark: hsl(0, 100%, 34%);--mainDarkest: hsl(0, 100%, 24%);--mainLight: hsl(0, 100%, 64%);--mainLightest: hsl(0, 100%, 74%);--searchBarFocusColor: hsl(0, 100%, 50%);--searchBarBorderColor: rgb(255, 71, 71, .1);--linksNoUnderline: #0969da;--linksNoUnderlineVisited: #085fc4}body.dark{--linksNoUnderline: #71b7ff;--linksNoUnderlineVisited: #65a4e5}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:300;src:url(./lato-latin-ext-300-normal-VPGGJKJL.woff2) format("woff2"),url(./lato-all-300-normal-GIV56FBX.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:300;src:url(./lato-latin-300-normal-YUMVEFOL.woff2) format("woff2"),url(./lato-all-300-normal-GIV56FBX.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-ext-400-normal-N27NCBWW.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-400-normal-W7754I4D.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-ext-700-normal-Q2L5DVMW.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-700-normal-2XVSBPG4.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:400;src:url(./inconsolata-vietnamese-400-normal-IGQPHHJH.woff2) format("woff2"),url(./inconsolata-all-400-normal-HMVRHNDU.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:400;src:url(./inconsolata-latin-ext-400-normal-K7HVGTP7.woff2) format("woff2"),url(./inconsolata-all-400-normal-HMVRHNDU.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:400;src:url(./inconsolata-latin-400-normal-RGKDDNDD.woff2) format("woff2"),url(./inconsolata-all-400-normal-HMVRHNDU.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:700;src:url(./inconsolata-vietnamese-700-normal-LHEGSN35.woff2) format("woff2"),url(./inconsolata-all-700-normal-WFUKXZPS.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:700;src:url(./inconsolata-latin-ext-700-normal-4MPBLFZC.woff2) format("woff2"),url(./inconsolata-all-700-normal-WFUKXZPS.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inconsolata;font-style:normal;font-display:swap;font-weight:700;src:url(./inconsolata-latin-700-normal-DTS2D7TO.woff2) format("woff2"),url(./inconsolata-all-700-normal-WFUKXZPS.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--content-width: 949px;--content-gutter: 60px;--borderRadius: 4px;--navTabBorderWidth: 4px;--defaultFontFamily: -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--sansFontFamily: "Lato", sans-serif;--monoFontFamily: "Inconsolata", Menlo, Courier, monospace;--baseFontSize: 18px;--baseLineHeight: 1.5em;--gray25: hsl(207, 43%, 98%);--gray50: hsl(207, 43%, 96%);--gray100: hsl(212, 33%, 91%);--gray200: hsl(210, 29%, 88%);--gray300: hsl(210, 26%, 84%);--gray400: hsl(210, 21%, 64%);--gray450: hsl(210, 21%, 49%);--gray500: hsl(210, 21%, 34%);--gray600: hsl(210, 27%, 26%);--gray700: hsl(212, 35%, 17%);--gray750: hsl(214, 46%, 14%);--gray800: hsl(216, 52%, 11%);--gray800-opacity-0: hsla(216, 52%, 11%, 0%);--gray850: hsl(216, 63%, 8%);--gray900: hsl(218, 73%, 4%);--gray900-opacity-50: hsla(218, 73%, 4%, 50%);--gray900-opacity-0: hsla(218, 73%, 4%, 0%);--coldGrayFaint: hsl(240, 5%, 97%);--coldGrayLight: hsl(240, 5%, 88%);--coldGray-lightened-10: hsl(240, 5%, 56%);--coldGray: hsl(240, 5%, 46%);--coldGray-opacity-10: hsla(240, 5%, 46%, 10%);--coldGrayDark: hsl(240, 5%, 28%);--coldGrayDim: hsl(240, 5%, 18%);--yellowLight: hsl(60, 100%, 81%);--yellowDark: hsl(60, 100%, 43%, 62%);--yellow: hsl(60, 100%, 43%);--green-lightened-10: hsl(90, 100%, 45%);--green: hsl(90, 100%, 35%);--white: hsl(0, 0%, 100%);--white-opacity-50: hsla(0, 0%, 100%, 50%);--white-opacity-10: hsla(0, 0%, 100%, 10%);--white-opacity-0: hsla(0, 0%, 100%, 0%);--black: hsl(0, 0%, 0%);--black-opacity-10: hsla(0, 0%, 0%, 10%);--black-opacity-50: hsla(0, 0%, 0%, 50%)}@media screen and (max-width: 768px){:root{--content-width: 100%;--content-gutter: 20px}}:root{--background: var(--white);--contrast: var(--black);--textBody: var(--gray800);--textHeaders: var(--gray900);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--coldGrayFaint);--textFooter: var(--gray700);--links: var(--black);--linksVisited: var(--black);--linksDecoration: var(--gray450);--iconAction: var(--coldGray);--iconActionHover: var(--gray800);--blockquoteBackground: var(--coldGrayFaint);--blockquoteBorder: var(--coldGrayLight);--tableHeadBorder: var(--gray100);--tableBodyBorder: var(--gray50);--warningBackground: hsl( 33, 100%, 97%);--warningHeadingBackground: hsl( 33, 87%, 64%);--warningHeading: var(--black);--errorBackground: hsl( 7, 81%, 96%);--errorHeadingBackground: hsl( 6, 80%, 60%);--errorHeading: var(--white);--infoBackground: hsl(206, 91%, 96%);--infoHeadingBackground: hsl(213, 92%, 62%);--infoHeading: var(--white);--neutralBackground: hsl(212, 29%, 92%);--neutralHeadingBackground: hsl(220, 43%, 11%);--neutralHeading: var(--white);--tipBackground: hsl(142, 31%, 93%);--tipHeadingBackground: hsl(134, 39%, 36%);--tipHeading: var(--white);--fnSpecAttr: var(--coldGray);--fnDeprecated: var(--yellowLight);--blink: var(--yellowLight);--codeBackground: var(--gray25);--codeBorder: var(--gray100);--codeScrollThumb: var(--gray400);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray25);--admCodeBorder: var(--gray100);--admCodeColor: var(--black);--admInlineCodeColor: var(--black);--admInlineCodeBackground: var(--gray25);--admInlineCodeBorder: var(--gray100);--tabBackground: var(--white);--tabBorder: var(--gray300);--tabBorderTop: var(--gray100);--tab: var(--gray600);--tabShadow: var(--gray25);--bottomActionsBtnBorder: var(--black-opacity-10);--bottomActionsBtnSubheader: var(--mainDark);--modalBackground: var(--white);--settingsInput: var(--gray500);--settingsInputBackground: var(--white);--settingsInputBorder: var(--gray300);--settingsSectionBorder: var(--gray300);--quickSwitchInput: var(--gray500);--quickSwitchContour: var(--coldGray);--success: var(--green);--sidebarAccentMain: var(--black);--sidebarBackground: var(--gray50);--sidebarHeader: var(--gray100);--sidebarMuted: var(--gray800);--sidebarHover: var(--black);--sidebarScrollbarThumb: var(--coldGrayLight);--sidebarScrollbarTrack: var(--sidebarBackground);--sidebarSubheadings: var(--black);--sidebarItem: var(--black);--sidebarInactiveItemBorder: var(--gray500);--sidebarInactiveItemMarker: var(--gray200);--sidebarLanguageAccentBar: var(--mainDark);--sidebarActiveItem: var(--mainDarkest);--searchBarBorder: var(--gray200);--searchAccentMain: var(--gray600);--searchLanguageAccentBar: var(--main);--searchSearch: var(--white);--autocompleteBorder: rgba(3, 9, 19, .1);--autocompletePreview: var(--gray25);--autocompleteHover: var(--grey50, #F0F5F9);--autocompleteBackground: var(--white);--suggestionBorder: var(--gray200);--autocompleteResults: var(--gray600);--autocompleteResultsBold: var(--gray800);--autocompleteSrollbarThumb: var(--gray200);--autocompleteSrollbarTrack: var(--gray50);--autocompleteLabelBack: var(--gray100);--autocompleteLabelFont: var(--gray600)}body.dark{--background: var(--gray900);--contrast: var(--white);--textBody: var(--gray200);--textHeaders: var(--gray100);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--gray700);--textFooter: var(--gray300);--links: var(--gray100);--linksVisited: var(--gray100);--linksDecoration: var(--gray450);--iconAction: var(--coldGray-lightened-10);--iconActionHover: var(--white);--blockquoteBackground: var(--coldGray-opacity-10);--blockquoteBorder: var(--coldGrayDim);--tableHeadBorder: var(--gray600);--tableBodyBorder: var(--gray700);--warningBackground: hsla( 33, 30%, 60%, 10%);--warningHeadingBackground: hsla( 33, 66%, 35%, 80%);--warningHeading: var(--white);--errorBackground: hsla( 7, 30%, 60%, 10%);--errorHeadingBackground: hsla( 6, 70%, 40%, 80%);--errorHeading: var(--white);--infoBackground: hsla(206, 30%, 60%, 10%);--infoHeadingBackground: hsla(213, 55%, 35%, 80%);--infoHeading: var(--white);--neutralBackground: hsl(210, 30%, 60%, 10%);--neutralHeadingBackground: var(--gray600);--neutralHeading: var(--white);--tipBackground: hsla(142, 30%, 60%, 10%);--tipHeadingBackground: hsla(134, 45%, 30%, 80%);--tipHeading: var(--white);--fnSpecAttr: var(--gray400);--fnDeprecated: var(--yellowDark);--blink: var(--gray600);--codeBackground: var(--gray750);--codeBorder: var(--gray600);--codeScrollThumb: var(--gray500);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray750);--admCodeBorder: var(--gray600);--admCodeColor: var(--gray100);--admInlineCodeColor: var(--gray100);--admInlineCodeBackground: var(--gray750);--admInlineCodeBorder: var(--gray600);--tabBackground: var(--gray900);--tabBorder: var(--gray700);--tabBorderTop: var(--gray700);--tab: var(--white);--tabShadow: var(--black);--bottomActionsBtnBorder: var(--white-opacity-10);--bottomActionsBtnSubheader: var(--mainLight);--modalBackground: var(--gray800);--settingsInput: var(--white);--settingsInputBackground: var(--gray700);--settingsInputBorder: var(--gray700);--settingsSectionBorder: var(--gray700);--quickSwitchInput: var(--gray300);--quickSwitchContour: var(--gray500);--success: var(--green-lightened-10);--sidebarAccentMain: var(--gray50);--sidebarBackground: var(--gray800);--sidebarHeader: var(--gray700);--sidebarMuted: var(--gray300);--sidebarHover: var(--white);--sidebarScrollbarThumb: var(--coldGray);--sidebarScrollbarTrack: var(--sidebarBackground);--sidebarSubheadings: var(--gray400);--sidebarItem: var(--gray200);--sidebarInactiveItemBorder: var(--gray400);--sidebarInactiveItemMarker: var(--gray600);--sidebarLanguageAccentBar: var(--mainLight);--sidebarActiveItem: var(--mainLightest);--searchBarBorder: var(--gray500);--searchAccentMain: var(--gray300);--searchSearch: var(--gray900);--autocompleteBorder: rgba(28,42,60,.75);--autocompletePreview: var(--gray750);--autocompleteHover: var(--gray700);--autocompleteBackground: var(--gray800);--suggestionBorder: var(--gray600);--autocompleteResults: var(--gray200);--autocompleteResultsBold: var(--gray100);--autocompleteSrollbarThumb: var(--gray600);--autocompleteSrollbarTrack: var(--gray850);--autocompleteLabelBack: var(--gray600);--autocompleteLabelFont: rgba(255, 255, 255, .8)}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}@font-face{font-family:remixicon;src:url(./remixicon-NKANDIL5.woff2) format("woff2");font-display:swap}[class^=ri-],[class*=" ri-"],.remix-icon{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}:root{--icon-arrow-up-s: "\ea78";--icon-arrow-down-s: "\ea4e";--icon-arrow-right-s: "\ea6e";--icon-add: "\ea13";--icon-subtract: "\f1af";--icon-error-warning: "\eca1";--icon-information: "\ee59";--icon-alert: "\ea21";--icon-double-quotes-l: "\ec51";--icon-link-m: "\eeaf";--icon-close-line: "\eb99";--icon-code-s-slash-line: "\ebad";--icon-menu-line: "\ef3e";--icon-search-2-line: "\f0cd";--icon-settings-3-line: "\f0e6";--icon-printer-line: "\f029"}.ri-lg{font-size:1.3333em;line-height:.75em;vertical-align:-.0667em}.ri-settings-3-line:before{content:var(--icon-settings-3-line)}.ri-add-line:before{content:var(--icon-add)}.ri-subtract-line:before{content:var(--icon-subtract)}.ri-arrow-up-s-line:before{content:var(--icon-arrow-up-s)}.ri-arrow-down-s-line:before{content:var(--icon-arrow-down-s)}.ri-arrow-right-s-line:before{content:var(--icon-arrow-right-s)}.ri-search-2-line:before{content:var(--icon-search-2-line)}.ri-menu-line:before{content:var(--icon-menu-line)}.ri-close-line:before{content:var(--icon-close-line)}.ri-link-m:before{content:var(--icon-link-m)}.ri-code-s-slash-line:before{content:var(--icon-code-s-slash-line)}.ri-error-warning-line:before{content:var(--icon-error-warning)}.ri-information-line:before{content:var(--icon-information)}.ri-alert-line:before{content:var(--icon-alert)}.ri-double-quotes-l:before{content:var(--icon-double-quotes-l)}.ri-printer-line:before{content:var(--icon-printer-line)}html,body{box-sizing:border-box;height:100%;width:100%}body{--sidebarWidth: 300px;--sidebarMinWidth: 300px;--sidebarTransitionDuration: .3s;background-color:var(--background);color:var(--textBody);font-size:16px;font-family:var(--sansFontFamily);line-height:1.6875em}*,*:before,*:after{box-sizing:inherit}.body-wrapper{display:flex;height:100%}.sidebar{display:flex;flex-direction:column;width:var(--sidebarWidth);min-width:var(--sidebarMinWidth);height:100%;position:fixed;top:0;left:0;z-index:100;resize:horizontal}.sidebar-button{padding:26px 12px 18px 19px;position:fixed;z-index:200;top:0;left:0;will-change:transform}.sidebar-toggle--animated.sidebar-button{transition:transform var(--sidebarTransitionDuration) ease-in-out}.content{width:calc(100% - var(--sidebarWidth));left:var(--sidebarWidth);height:100%;position:absolute}.content .content-inner{max-width:var(--content-width);min-height:100%;margin:0 auto;padding:0 var(--content-gutter) 10px}.content-inner:focus{outline:none}body:is(.sidebar-opening,.sidebar-opened) .sidebar-button{transform:translate(calc(var(--sidebarWidth) - 100%))}body.sidebar-opening-start .sidebar{left:calc(-1 * var(--sidebarWidth))}body.sidebar-opening-start .content{width:100%;left:0}body.sidebar-opening .sidebar{left:0;transition:left var(--sidebarTransitionDuration) ease-in-out}body.sidebar-opening .content{width:calc(100% - var(--sidebarWidth));left:var(--sidebarWidth);transition:all var(--sidebarTransitionDuration) ease-in-out}body.sidebar-closing .sidebar-button{transform:translate(0)}body.sidebar-closing .sidebar{left:calc(-1 * var(--sidebarWidth));transition:left var(--sidebarTransitionDuration) ease-in-out}body.sidebar-closing .content{width:100%;left:0;transition:all var(--sidebarTransitionDuration) ease-in-out}body.sidebar-closed .sidebar{left:calc(-1 * var(--sidebarWidth));display:none}body.sidebar-closed .content{width:100%;left:0}@media screen and (max-width: 768px){.content,body.sidebar-opening .content{left:0;width:100%}body.sidebar-closed .sidebar-button{position:absolute}}.sidebar{--sidebarFontSize: 16px;--sidebarLineHeight: 20px;font-family:var(--sansFontFamily);font-size:var(--sidebarFontSize);font-weight:300;line-height:var(--sidebarLineHeight);background-color:var(--sidebarBackground);color:var(--sidebarAccentMain);overflow:hidden;scrollbar-color:var(--sidebarScrollbarThumb) var(--sidebarScrollbarTrack)}.non-apple-os .sidebar{font-weight:400}.sidebar ul{list-style:none}.sidebar ul li{margin:0;padding:0 10px}.sidebar a{color:var(--sidebarAccentMain);text-decoration:none;transition:color .3s ease-in-out}.sidebar a:hover{color:var(--sidebarHover)}.sidebar .sidebar-header{background-color:var(--sidebarHeader);width:100%}.sidebar .sidebar-projectInfo{display:flex;justify-content:start;align-items:center;gap:16px;margin:12px 16px 12px 14px;max-width:235px}.sidebar .sidebar-projectImage{align-self:flex-end}.sidebar .sidebar-projectImage img{display:block;max-width:48px;max-height:48px}.sidebar .sidebar-projectName{font-weight:700;font-size:20px;line-height:24px;color:var(--sidebarAccentMain);margin:0;padding:0;max-width:230px;word-wrap:break-word}.sidebar .sidebar-projectVersion{display:block;position:relative;margin:0;padding:0;font-size:var(--sidebarFontSize);line-height:var(--sidebarLineHeight);color:var(--sidebarMuted)}.sidebar .sidebar-projectVersionsDropdown{cursor:pointer;position:relative;margin:0;padding:0 0 0 12px;border:none;-webkit-appearance:none;appearance:none;background-color:transparent;color:var(--sidebarMuted);z-index:2}.sidebar .sidebar-projectVersionsDropdown option{color:initial}.sidebar .sidebar-projectVersionsDropdownCaret{position:absolute;left:0;top:2px;z-index:1;font-size:8px;color:var(--sidebarMuted)}.sidebar .sidebar-projectVersionsDropdown::-ms-expand{display:none}.sidebar .sidebar-listNav{display:flex;margin:0;padding:4px 4px 0}.sidebar .sidebar-listNav :is(li,li button){text-transform:uppercase;letter-spacing:.02em;font-size:14px;color:var(--sidebarMuted)}.sidebar .sidebar-listNav li{display:inline-block;padding:0}.sidebar .sidebar-listNav li button{background:none;border:0;border-radius:0;-webkit-appearance:none;text-align:inherit;color:inherit;font-weight:inherit;cursor:pointer;display:inline-block;line-height:27px;padding:4px 10px 2px;transition:all .15s}.sidebar .sidebar-listNav li:is(.selected) button{background-color:var(--sidebarBackground);border-top:var(--navTabBorderWidth) solid var(--sidebarLanguageAccentBar)}.sidebar .sidebar-listNav li:not(.selected) button{border-top:var(--navTabBorderWidth) solid var(--sidebarHeader)}.sidebar .sidebar-listNav li:is(:hover):not(.selected) button{background-color:var(--sidebarInactiveItemMarker);border-top:var(--navTabBorderWidth) solid var(--sidebarInactiveItemBorder);color:var(--sidebarAccentMain);transition:all .15s}.sidebar .sidebar-tabpanel{flex:1 1 .01%;overflow-y:auto;overscroll-behavior:contain;position:relative;-webkit-overflow-scrolling:touch;margin-top:12px}.sidebar .full-list{margin:0;padding:0 0 20px;position:relative}.sidebar .full-list :is(li,a){overflow:hidden;text-overflow:ellipsis}.sidebar .full-list li{padding:0;margin-right:30px;line-height:27px;white-space:nowrap}.sidebar .full-list li.docs{margin-right:0}.sidebar .full-list li.open>ul{display:block;margin-left:10px}.sidebar .full-list li a.expand+button.icon-expand{appearance:none;background-color:transparent;border:0;padding:0;cursor:pointer;color:inherit;margin-right:10px;font-size:calc(1.2 * var(--sidebarFontSize));line-height:var(--sidebarLineHeight);position:absolute;display:flex;right:0;transform:translateY(calc(-100% - 4px))}.sidebar .full-list li a+button.icon-expand:after{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sidebar .full-list li a.expand+button.icon-expand:after{content:var(--icon-arrow-down-s)}.sidebar .full-list li.open>a.expand+button.icon-expand:after{content:var(--icon-arrow-up-s)}.sidebar .full-list li.docs>a+button.icon-expand{margin-right:12px;font-size:var(--sidebarFontSize);line-height:var(--sidebarFontSize);transform:translateY(calc(-100% - 5px))}.sidebar .full-list li.docs>a+button.icon-expand:after{content:var(--icon-add)}.sidebar .full-list li.docs.open>a+button.icon-expand:after{content:var(--icon-subtract)}.sidebar .full-list li.nesting-context{font-weight:700;font-size:.9em;line-height:1.8em;color:var(--sidebarSubheadings);margin-top:10px;padding-left:15px}.sidebar .full-list li.group{text-transform:uppercase;font-weight:700;font-size:.8em;margin:1.5em 0 0;line-height:1.8em;color:var(--sidebarSubheadings);padding-left:15px}.sidebar .full-list li a{padding:3px 0 3px 15px;color:var(--sidebarItem)}.sidebar .full-list>li>a{display:block;width:100%;height:27px;line-height:var(--sidebarLineHeight)}.sidebar .full-list li .current-section>a{color:var(--sidebarActiveItem)}.sidebar .full-list li .current-section>a+button.icon-expand{color:var(--sidebarActiveItem)}.sidebar .full-list>li>a:hover{border-left:3px solid var(--sidebarLanguageAccentBar);padding-left:12px}.sidebar .full-list>li.current-page>a{color:var(--sidebarActiveItem);border-left:3px solid var(--sidebarLanguageAccentBar);padding-left:12px}.sidebar .full-list>li.current-page>a:after,.sidebar .full-list>li.current-page{color:var(--sidebarActiveItem)}.sidebar .full-list>li:last-child{margin-bottom:30px}.sidebar .full-list>li.group:first-child{margin-top:0}.sidebar .full-list ul{display:none;margin:10px 0 10px 15px;padding:0}.sidebar .full-list ul li{font-weight:300;line-height:var(--sidebarFontSize);padding:0 8px;margin-right:0;color:var(--sidebarAccentMain)}.non-apple-os .sidebar .full-list ul li{font-weight:400}.sidebar .full-list ul li.current-hash{color:var(--sidebarActiveItem)}.sidebar .full-list ul li.current-hash>a{color:var(--sidebarActiveItem)}.sidebar .full-list ul li.current-hash>a:before,.sidebar .full-list>li>ul>li>a:hover:before{content:"\2022";position:absolute;margin-left:-15px;color:var(--sidebarActiveItem)}.sidebar .full-list ul li a{padding-left:15px;display:block;width:100%;height:24px}.sidebar .full-list ul li ul{display:none;margin:9px 0 9px 20px}.sidebar .full-list ul li ul li{margin-right:0;height:20px;color:var(--sidebarAccentMain)}.sidebar .full-list ul li ul li a{border-left:1px solid var(--sidebarInactiveItemMarker);padding:0 10px;height:20px}.sidebar .full-list ul li ul li.current-hash>a:before{content:none}.sidebar .full-list ul li ul li>a:hover{border-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list ul li ul li.current-hash>a{color:var(--sidebarActiveItem);border-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list ul li ul li.current-hash>a{color:var(--sidebarActiveItem);margin-left:0}.sidebar ::-webkit-scrollbar{width:14px}::-webkit-scrollbar-track{background-color:var(--sidebarBackground)}.sidebar ::-webkit-scrollbar-thumb{background-color:var(--sidebarScrollbarThumb);border-radius:10px;border:3px solid var(--sidebarBackground)}.sidebar-button{cursor:pointer;background-color:transparent;border:none;font-size:var(--sidebarFontSize)}.sidebar-button:hover{color:var(--sidebarHover)}.sidebar-button{color:var(--sidebarAccentMain)}.sidebar-closed .sidebar-button{color:var(--contrast)}@media screen and (max-height: 500px){.sidebar{overflow-y:auto}.sidebar .full-list{overflow:visible}}.top-search{background-color:var(--background);top:0;z-index:99;position:relative;width:100%;padding:10px 0}.search-settings{display:flex;column-gap:12px;align-items:center;width:100%;position:relative}.search-bar{border:1px solid var(--searchBarBorder);border-radius:8px;height:48px;position:relative;width:100%}.top-search .search-bar .search-input{background-color:var(--searchSearch);border:1px solid transparent;border-radius:8px;color:var(--searchAccentMain);position:relative;height:46px;padding:8px 35px 8px 43px;width:100%}.top-search .search-bar .search-input::placeholder{color:var(--searchAccentMain);opacity:.5}.top-search .search-bar .search-input:focus{border:1px solid var(--searchBarFocusColor);border-radius:7px;position:relative;box-shadow:0 4px 20px 0 var(--searchBarBorderColor) inset}.top-search .search-bar .search-label{position:relative}.top-search .search-bar .search-button{font-size:14px;color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;left:11px;opacity:.5;padding:5px 1px 5px 5px;position:absolute;top:60%;transform:translateY(-60%);z-index:99}.top-search .search-bar.selected .search-button,.top-search .search-bar .search-button:hover,.top-search .search-bar .search-button:focus{color:var(--top-searchLanguageAccentBar);opacity:1}.top-search .search-bar .search-close-button{font-size:16px;color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;right:11px;margin:0;opacity:.5;padding:5px 1px 5px 0;position:absolute;transform:scaleY(0);top:calc(50% - 13px);transition:.15s transform ease-out;z-index:99}.top-search .search-bar .search-close-button:hover{opacity:.7}.top-search .search-settings button.icon-settings{display:flex;align-items:center;justify-content:flex-end}.top-search .search-settings .icon-settings{font-size:20px;float:right;color:var(--iconAction);text-decoration:none;border:none;transition:color .3s ease-in-out;background-color:transparent;cursor:pointer;padding:0}.top-search .search-settings .icon-settings:hover{color:var(--iconActionHover)}.top-search .search-settings .icon-settings:visited{color:var(--iconAction)}@media screen and (max-width: 768px){.top-search{padding-left:calc(var(--content-gutter) + 36px);padding-right:var(--content-gutter);margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));width:calc(2 * var(--content-gutter) + 100%)}.search-settings{width:100%;box-sizing:border-box}}body.search-focused .search-bar .search-close-button{transform:scaleY(1);transition:transform .15s ease-out .15s}@media screen and (hover: hover){body.search-focused .top-search{position:sticky!important}body.search-focused.sidebar-closed .sidebar-button{position:fixed!important}}@media screen and (hover: none){body.scroll-sticky .top-search{position:sticky!important}body.scroll-sticky.sidebar-closed .sidebar-button{position:fixed!important}}*:focus,button:focus,[type=button]:focus,[type=reset]:focus,[type=submit]:focus{outline:2px solid var(--main);outline-offset:-2px}*:focus:not(:focus-visible),button:focus:not(:focus-visible),[type=button]:focus:not(:focus-visible),[type=reset]:focus:not(:focus-visible),[type=submit]:focus:not(:focus-visible){outline:0}input[type=text],input[type=number],input[type=date],input[type=datetime],input[type=datetime-local],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=time],input[type=url],input[type=week],textarea{outline:0}.content-inner{font-family:var(--defaultFontFamily);font-size:1em;line-height:1.6875em;position:relative;background-color:var(--background);color:var(--textBody)}.content-inner :is(h1,h2,h3,h4,h5,h6){font-family:var(--sansFontFamily);font-weight:700;line-height:1.5em;word-wrap:break-word;color:var(--textHeaders)}.content-inner h1{font-size:2em;margin:.5em 0}.content-inner h1.signature{margin:0}.content-inner h1.section-heading{margin:1.5em 0 .5em}.content-inner h1 small{font-weight:300}.content-inner h1 .icon-action{font-size:1.2rem;font-weight:400}.content-inner h2{font-size:1.6em;margin:1em 0 .5em;font-weight:700}.content-inner h3{font-size:1.375em;margin:1em 0 .5em;font-weight:700}.content-inner li+li{margin-top:.25em}.content-inner :is(a,.a-main){color:var(--links);text-decoration:underline;text-decoration-color:var(--linksDecoration);text-decoration-skip-ink:auto}.content-inner :is(a:visited,.a-main:visited){color:var(--linksVisited)}.content-inner .icon-action{float:right;color:var(--iconAction);text-decoration:none;border:none;transition:color .3s ease-in-out;background-color:transparent;cursor:pointer}.content-inner button.icon-action{margin-top:12px}.content-inner .icon-action:hover{color:var(--iconActionHover)}.content-inner .icon-action:visited{color:var(--iconAction)}.content-inner .livebook-badge-container{display:flex}.content-inner a.livebook-badge{display:inline-flex}.content-inner .note{color:var(--iconAction);margin-right:5px;font-size:14px;font-weight:400}.content-inner blockquote,.content-inner section.admonition{border-left:3px solid var(--blockquoteBorder);position:relative;margin:1.5625em 0;padding:0 1.2rem;overflow:auto;background-color:var(--blockquoteBackground);border-radius:var(--borderRadius)}.content-inner blockquote p:last-child,.content-inner section.admonition p:last-child{padding-bottom:1em;margin-bottom:0}.content-inner table{margin:2em 0;border-collapse:collapse}.content-inner th{text-align:left;font-family:var(--sansFontFamily);text-transform:uppercase;font-weight:700;padding-bottom:.5em}.content-inner thead tr{border-bottom:1px solid var(--tableHeadBorder)}.content-inner tbody tr{border-bottom:1px solid var(--tableBodyBorder)}.content-inner tbody tr:last-child{border-bottom:none}.content-inner tr{vertical-align:bottom;height:2.5em}.content-inner :is(td,th){padding:.25em .25em .25em 1em;line-height:2em;vertical-align:top}.content-inner .section-heading{--icon-size: 16px;--icon-spacing: 5px;display:grid;grid-template:1fr / 1fr}.content-inner .section-heading>:is(.hover-link,.text){grid-row:1;grid-column:1}.content-inner .section-heading .hover-link{text-decoration:none}.content-inner .section-heading i{font-size:var(--icon-size);margin-top:.1em;margin-left:calc(-1 * (var(--icon-size) + var(--icon-spacing)));padding-right:var(--icon-spacing);opacity:0}@media screen and (max-width: 768px){.content-inner .section-heading i{margin-left:calc(-1 * (var(--icon-size)))}}.content-inner :is(blockquote,section.admonition) .section-heading i{display:none}.content-inner .section-heading .hover-link:is(:hover,:focus) i{opacity:1}.content-inner .section-heading .text{pointer-events:none}.content-inner .section-heading .text a{pointer-events:all}.content-inner .app-vsn{display:none!important;font-size:.6em;line-height:1.5em}@media screen and (max-width: 768px){.content-inner .app-vsn{display:block!important}}.content-inner img{max-width:100%}.content-inner strong>code{font-weight:700}.content-inner code{font-family:var(--monoFontFamily);font-style:normal;line-height:24px;font-weight:400}@media screen and (max-width: 768px){.content-inner :is(ol,ul){padding-left:calc(1.5 * var(--content-gutter))}}.content-inner section.admonition{border-radius:10px;border-left:0}.content-inner section.admonition.warning{background-color:var(--warningBackground)}.content-inner section.admonition.error{background-color:var(--errorBackground)}.content-inner section.admonition.info{background-color:var(--infoBackground)}.content-inner section.admonition.neutral{background-color:var(--neutralBackground)}.content-inner section.admonition.tip{background-color:var(--tipBackground)}.content-inner section.admonition>.admonition-title{color:var(--contrast);margin:0 -1.2rem;padding:.7rem 1.2rem .7rem 3.3rem;font-weight:700;font-style:normal}.content-inner section.admonition>.admonition-title:before{color:var(--contrast);position:absolute;left:1rem;font-size:1.8rem;font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.content-inner section.admonition>.admonition-title.warning{background-color:var(--warningHeadingBackground);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.warning:before{content:var(--icon-error-warning);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.error{background-color:var(--errorHeadingBackground);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.error:before{content:var(--icon-error-warning);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.info{background-color:var(--infoHeadingBackground);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.info:before{content:var(--icon-information);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.neutral{background-color:var(--neutralHeadingBackground);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.neutral:before{content:var(--icon-double-quotes-l);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.tip{background-color:var(--tipHeadingBackground);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title.tip:before{content:var(--icon-information);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title code{margin:0 .5ch}.content-inner section.admonition code{background-color:var(--admInlineCodeBackground);border:1px solid var(--admInlineCodeBorder);color:var(--admInlineCodeColor)}.content-inner section.admonition pre code{background-color:var(--admCodeBackground);border:1px solid var(--admCodeBorder);color:var(--admCodeColor)}.content-inner section.admonition>.admonition-title :is(a,a:visited){color:inherit;text-decoration-color:currentColor}@media screen and (max-width: 768px){.content-inner section.admonition{margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0}.content-inner section.admonition>.admonition-title{margin:0 calc(-1 * var(--content-gutter))}}.content-inner .summary h2{font-weight:700}.content-inner .summary h2 a{text-decoration:none;border:none}.content-inner .summary span.deprecated{color:var(--darkDeprecated);font-weight:400;font-style:italic}.content-inner .summary .summary-row .summary-signature{font-family:var(--monoFontFamily);font-weight:700}.content-inner .summary .summary-row .summary-signature a{text-decoration:none;border:none}.content-inner .summary .summary-row .summary-synopsis{font-family:var(--defaultFontFamily);font-style:italic;padding:0 1.2em;margin:0 0 .5em}.content-inner .summary .summary-row .summary-synopsis p{margin:0;padding:0}.content-inner :is(a.no-underline,pre a){color:var(--linksNoUnderline);text-shadow:none;text-decoration:none;background-image:none}.content-inner :is(a.no-underline,pre a):is(:visited,:active,:focus,:hover){color:var(--linksNoUnderlineVisited)}.content-inner code{background-color:var(--codeBackground);vertical-align:baseline;border-radius:2px;padding:.1em .2em;border:1px solid var(--codeBorder);text-transform:none}.content-inner pre{margin:var(--baseLineHeight) 0}.content-inner pre code{display:block;overflow-x:auto;white-space:inherit;padding:.5em 1em}.content-inner pre code::-webkit-scrollbar{width:.4rem;height:.4rem}.content-inner pre code::-webkit-scrollbar-thumb{border-radius:.25rem;background-color:var(--codeScrollThumb)}.content-inner pre code::-webkit-scrollbar-track{background-color:var(--codeScrollBackground)}.content-inner pre code::-webkit-scrollbar-corner{background-color:var(--codeScrollBackground)}.content-inner pre code.output{margin:0 12px;max-height:400px;overflow:auto}.content-inner pre code.output+.copy-button{margin-right:12px}.content-inner pre code.output:before{content:"Output";display:block;position:absolute;top:-16px;left:12px;padding:2px 4px;font-size:12px;font-family:var(--monoFontFamily);line-height:1;color:var(--textHeaders);background-color:var(--codeBackground);border:1px solid var(--codeBorder);border-bottom:0;border-radius:2px}@media screen and (max-width: 768px){.content-inner>pre,.content-inner section>pre{margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter))}.content-inner>pre code,.content-inner section>pre code{padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0;border-left-width:0;border-right-width:0}}@keyframes blink-background{0%{background-color:var(--textDetailBackground)}to{background-color:var(--blink)}}.content-inner .detail:target .detail-header{animation-duration:.55s;animation-name:blink-background;animation-iteration-count:1;animation-timing-function:ease-in-out}.content-inner .detail-header{margin:2 0 1em;padding:.5em 1em;background-color:var(--textDetailBackground);border-left:3px solid var(--textDetailAccent);font-size:1em;font-family:var(--monoFontFamily);position:relative}.content-inner .detail-header .note{float:right}.content-inner .detail-header .signature{display:inline-block;font-family:var(--monoFontFamily);font-size:1rem;font-weight:700}.content-inner .detail-header:hover a.detail-link,.content-inner .detail-header a.detail-link:focus{opacity:1;text-decoration:none}.content-inner .detail-header a.detail-link{transition:opacity .3s ease-in-out;position:absolute;top:0;left:0;display:block;opacity:0;padding:.6em;line-height:1.5em;margin-left:-2.5em;text-decoration:none;border:none}@media screen and (max-width: 768px){.content-inner .detail-header a.detail-link{margin-left:-30px}}.content-inner .specs pre{font-family:var(--monoFontFamily);font-size:.9em;font-style:normal;line-height:24px;white-space:pre-wrap;margin:0;padding:0}.content-inner .specs .attribute{color:var(--fnSpecAttr)}.content-inner .docstring{margin:1.2em 0 3em 1.2em}@media screen and (max-width: 768px){.content-inner .docstring{margin-left:0}}.content-inner .docstring:is(h2,h3,h4,h5){font-weight:700}.content-inner .docstring h2{font-size:1.1em}.content-inner .docstring h3{font-size:1em}.content-inner .docstring h4{font-size:.95em}.content-inner .docstring h5{font-size:.9em}.content-inner div.deprecated{display:block;padding:9px 15px;background-color:var(--fnDeprecated)}.content-inner .footer{margin:4em auto 1em;text-align:center;font-style:italic;font-size:14px}.content-inner .footer,.content-inner .footer :is(a,.footer-button){color:var(--textFooter)}.content-inner .footer .line{display:inline-block}.content-inner .footer .footer-button{background-color:transparent;border:0;cursor:pointer;font-style:italic;padding:0 4px}.content-inner .footer .footer-hex-package{margin-right:4px}.content-inner .bottom-actions{display:flex;justify-content:space-between;margin-top:4em}.content-inner .bottom-actions .bottom-actions-button{display:flex;text-decoration:none;flex-direction:column;border-radius:var(--borderRadius);border:1px solid var(--bottomActionsBtnBorder);padding:8px 16px;min-width:150px}.content-inner .bottom-actions .bottom-actions-button .subheader{font-size:.8em;color:var(--bottomActionsBtnSubheader);white-space:nowrap}.content-inner .bottom-actions .bottom-actions-button[rel=prev] .subheader{text-align:right}@media screen and (max-width: 768px){.content-inner .bottom-actions{flex-direction:column-reverse}.content-inner .bottom-actions .bottom-actions-item:not(:first-child){margin-bottom:16px}}.page-cheatmd .content-inner{--horizontal-space: 1.5em;--vertical-space: 1em}@media (max-width: 600px){.page-cheatmd .content-inner{--horizontal-space: 1em;--vertical-space: .75em}}.page-cheatmd .content-inner{max-width:1200px}.page-cheatmd .content-inner h1{margin-bottom:var(--vertical-space)}.page-cheatmd .content-inner h2{margin:var(--vertical-space) 0;column-span:all;color:var(--gray700);font-weight:500}.page-cheatmd.dark .content-inner h2{color:var(--gray200)}.page-cheatmd .content-inner h3{color:var(--main);text-decoration-color:var(--main);margin:0 0 1em;font-weight:400}.page-cheatmd .content-inner h3 :is(a,a:visited){color:var(--main);text-decoration-color:var(--main)}.page-cheatmd .content-inner section.h3{min-width:300px;margin:0;padding:0 0 calc(var(--vertical-space) * 2) 0;break-inside:avoid}.page-cheatmd .content-inner h3 .text{overflow:hidden}.page-cheatmd .content-inner h3 .text:after{content:"";margin-left:calc(var(--horizontal-space) / 2);vertical-align:baseline;display:inline-block;width:100%;height:1px;margin-right:-100%;margin-bottom:5px;background-color:var(--codeBorder)}.page-cheatmd .content-inner h4{display:block;margin:0;padding:.25em var(--horizontal-space);font-weight:400;background:var(--gray100);color:#567;border:solid 1px 1px 0 1px var(--gray100)}.page-cheatmd.dark .content-inner h4{background:#192f50;color:var(--textBody);border:1px solid #192f50;border-bottom:0}.page-cheatmd .content-inner .h2 p{margin:0;display:block;background:var(--gray50);padding:var(--vertical-space) var(--horizontal-space)}.page-cheatmd.dark .content-inner .h2 p{background:var(--gray700)}.page-cheatmd .content-inner .h2 p>code{color:#eb5757;border-radius:var(--borderRadius);padding:.2em .4em}.page-cheatmd .content-inner pre code{padding:var(--vertical-space) var(--horizontal-space)}.page-cheatmd .content-inner pre code::-webkit-scrollbar{width:.4rem;height:.6rem}.page-cheatmd .content-inner .h2 pre{margin:0}.page-cheatmd .content-inner .h2 pre+pre{margin-top:-1px}.page-cheatmd .content-inner pre.wrap{white-space:break-spaces}@media screen and (max-width: 768px){.page-cheatmd .content-inner pre code{border-left-width:1px!important;border-right-width:1px!important}}.page-cheatmd .content-inner .h2 table{display:table;box-sizing:border-box;width:100%;border-collapse:collapse;margin:0}.page-cheatmd .content-inner .h2 th{padding:var(--vertical-space) var(--horizontal-space);line-height:inherit;margin-bottom:-1px;vertical-align:middle;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td{padding:var(--vertical-space) var(--horizontal-space);border:0;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 tr:first-child{border-top:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td code{color:#eb5757;border-radius:var(--borderRadius);padding:.2em .4em}.page-cheatmd .content-inner .h2 thead{background-color:var(--gray50)}.page-cheatmd.dark .content-inner .h2 thead{background-color:var(--gray700)}.page-cheatmd .content-inner .h2 tbody{background-color:var(--codeBackground)}.page-cheatmd .content-inner .h2 :is(ul,ol){margin:0;padding:0}.page-cheatmd .content-inner .h2 li{list-style-position:inside;padding:.5em var(--horizontal-space);line-height:2em;vertical-align:middle;background-color:var(--codeBackground);border-bottom:1px solid var(--codeBorder);margin-top:0}.page-cheatmd .content-inner .h2 :is(ul,ol)+pre code{border-top:0}.page-cheatmd .content-inner .h2 li>code{color:#eb5757;border-radius:var(--borderRadius);padding:.2em .4em}.page-cheatmd .content-inner section.width-50{display:block;width:50%;margin:0}.page-cheatmd .content-inner section.width-50>section>table{width:100%}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:40px}.page-cheatmd .content-inner section.col-2{column-count:2;height:auto}.page-cheatmd .content-inner section.col-2-left{display:grid;grid-template-columns:calc(100% / 3) auto}.page-cheatmd .content-inner section.col-2-left>h2{grid-column-end:span 2}.page-cheatmd .content-inner section.col-3{column-count:3;height:auto}.page-cheatmd .content-inner section.list-4>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-4>ul>li{flex:0 0 25%}.page-cheatmd .content-inner section.list-6>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 calc(100% / 6)}@media screen and (max-width: 1400px){.page-cheatmd .content-inner section.col-3{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:flex;flex-direction:column}}@media screen and (max-width: 1200px){.page-cheatmd .content-inner section:is(.col-2,.col-3){display:flex;flex-direction:column}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 25%}}@media screen and (max-width: 1000px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 calc(100% / 3)}}@media screen and (max-width: 600px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 50%}.page-cheatmd .content-inner section.width-50{width:100%}}#search{min-height:200px;position:relative}#search .loading{height:64px;width:64px;position:absolute;top:50%;left:calc(50% - 32px)}#search .loading div{box-sizing:border-box;display:block;position:absolute;width:51px;height:51px;margin:6px;border:6px solid var(--coldGray);border-radius:50%;animation:loading 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:var(--coldGray) transparent transparent transparent}#search .loading div:nth-child(1){animation-delay:-.45s}#search .loading div:nth-child(2){animation-delay:-.3s}#search .loading div:nth-child(3){animation-delay:-.15s}@keyframes loading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}#search .result{margin:2em 0 2.5em}#search .result p{margin:0}#search .result-id{font-size:1.4em;margin:0}#search .result-id a{text-decoration:none;transition:color .1s ease-in-out;color:var(--links)}#search .result-id a:is(:visited,:active,:focus){color:var(--linksVisited)}#search .result-id a:hover{color:var(--main)}#search :is(.result-id,.result-elem) em{font-style:normal;color:var(--main)}#search .result-id small{font-weight:400}@keyframes keyboard-shortcuts-show{0%{opacity:0}to{opacity:1}}.modal{animation-duration:.15s;animation-name:keyboard-shortcuts-show;animation-iteration-count:1;animation-timing-function:ease-in-out;display:none;background-color:#000000bf;position:fixed;inset:0;z-index:300}.modal.shown{display:block}.modal .modal-contents{margin:75px auto 0;max-width:500px;background-color:var(--modalBackground);border-radius:var(--borderRadius);box-shadow:2px 2px 8px #0003;padding:25px 35px 35px}@media screen and (max-width: 768px){.modal .modal-contents{padding:20px}}.modal .modal-header{display:flex;align-items:start}.modal .modal-title{display:inline-block;flex-grow:1;font-size:1.2rem;font-weight:700;margin-bottom:20px}.modal .modal-title button{border:none;background-color:transparent;color:var(--textHeaders);font-weight:700;margin-right:30px;padding-left:0;text-align:left;transition:color .15s}.modal .modal-title button:hover{color:var(--main);cursor:pointer}.modal .modal-title button.active{color:var(--main)}.modal .modal-close{cursor:pointer;display:block;font-size:1.5rem;margin:-8px -8px 0 0;padding:8px;opacity:.7;background-color:transparent;color:var(--textHeaders);border:none;transition:opacity .15s}.modal .modal-close:hover{opacity:1}#keyboard-shortcuts-content dl.shortcut-row{display:flex;align-items:center;justify-content:space-between;margin:0;padding:6px 0 8px;border-bottom:1px solid var(--settingsSectionBorder)}#keyboard-shortcuts-content dl.shortcut-row:last-of-type{border-bottom-style:none}#keyboard-shortcuts-content dl.shortcut-row:first-child{padding-top:0}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){display:inline-block}#keyboard-shortcuts-content kbd>kbd{background-color:var(--settingsInputBorder);color:var(--contrast);border-radius:var(--borderRadius);font-family:inherit;font-weight:700;display:inline-block;line-height:1;padding:4px 7px 6px;min-width:26px;text-align:center}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){margin:0}#quick-switch-modal-body{width:100%;position:relative}#quick-switch-modal-body .ri-search-2-line{position:absolute;left:0;top:0;padding:4px 10px;color:var(--quickSwitchContour);font-weight:700}#quick-switch-modal-body #quick-switch-input{width:100%;padding:8px 6px 8px 38px;border:none;color:var(--quickSwitchInput);background-color:transparent;border-bottom:1px solid var(--quickSwitchContour);box-sizing:border-box;transition:all .12s ease-out}#quick-switch-modal-body #quick-switch-results{margin:0}#quick-switch-modal-body .quick-switch-result{padding:2px 5px;border-bottom:1px dotted var(--quickSwitchContour);transition:all .12s ease-out}#quick-switch-modal-body .quick-switch-result:last-child{border-bottom:none}#quick-switch-modal-body .quick-switch-result:hover{cursor:pointer}#quick-switch-modal-body .quick-switch-result:is(:hover,.selected){border-left:4px solid var(--main);background-color:var(--codeBackground)}.autocomplete{display:none;position:absolute;width:calc(100% - 32px);top:55px}.autocomplete .triangle{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-bottom:12px solid var(--autocompleteBackground);position:absolute;top:8px;left:26px;transform:translate(-50%);z-index:100;background-color:transparent}.autocomplete-preview{width:100%;margin:0;height:100%;line-height:20px;background-color:var(--background);font-family:var(--sansFontFamily);border:4px solid var(--autocompleteBorder);padding:12px 16px}.autocomplete-preview div,.autocomplete-preview span{display:none}.autocomplete-preview.loading div{float:left;display:block;border:5px solid var(--autocompleteBorder);border-radius:50%;border-top:5px solid var(--textDetailAccent);width:20px;height:20px;animation:spinner 4s linear infinite}.autocomplete-preview.loading span{color:var(--autocompleteResults);display:inline;margin-left:6px}.autocomplete-preview.loading span:after{color:var(--autocompleteResults);content:"Loading"}@keyframes spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.autocomplete-preview.loading iframe{height:0}.autocomplete-preview iframe{width:100%;height:100%;border:0}.autocomplete-results{list-style:none;margin:0;padding:15px 20px;display:flex;justify-content:space-between;color:var(--autocompleteResults);font-family:var(--sansFontFamily);font-weight:300;font-size:.9rem}.autocomplete-results .bold{color:var(--autocompleteResultsBold);font-weight:400}.autocomplete.shown{display:block}.autocomplete-container{position:absolute;top:15px;width:100%;z-index:200}.autocomplete-suggestions{background-color:var(--autocompleteBackground);border-radius:8px;box-shadow:0 15px 99px 0 var(--autocompleteBorder);overflow-y:auto;max-height:450px;white-space:normal;overflow-x:hidden;overscroll-behavior-y:contain}.autocomplete-suggestions.previewing:has(.selected){max-height:80vh}.autocomplete-suggestions.previewing:has(.selected) .autocomplete-suggestion:not(.selected){display:none}.autocomplete-suggestions.previewing:not(:has(.selected)) .autocomplete-preview{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview{display:none}.autocomplete-suggestion{color:inherit;display:block;padding:12px 20px;text-decoration:none;transition:background-color .3s ease-in-out;border-top:1px solid var(--suggestionBorder);font-size:.9rem}.autocomplete-suggestion:hover,.autocomplete-suggestion.selected{background-color:var(--autocompleteHover)}.autocomplete-suggestion:not(.selected) .autocomplete-preview-indicator{display:none}.autocomplete-preview-indicator{float:right}.autocomplete-preview-indicator button{color:var(--iconAction);display:flex;align-items:center;text-decoration:none;border:1px solid var(--suggestionBorder);border-radius:8px;transition:color .3s ease-in-out;background-color:var(--autocompletePreview);cursor:pointer;padding:4px 8px;font-size:14px}.autocomplete-preview-indicator button:hover{color:var(--iconActionHover);background-color:var(--autocompleteHover)}.autocomplete-preview-indicator button i{margin-right:4px}.autocomplete-suggestions.previewing .autocomplete-preview-indicator-closed{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview-indicator-open{display:none}.autocomplete-suggestion:hover:not(.selected) .autocomplete-preview-indicator-closed{display:block}.autocomplete-suggestion em{font-style:normal;font-weight:700}.autocomplete-suggestion .description{opacity:.6;padding-top:3px}.autocomplete-suggestion .label{background-color:var(--autocompleteLabelBack);opacity:.6;color:var(--autocompleteLabelFont);padding:4px 8px;border-radius:4px;margin-left:5px;text-transform:uppercase;font-family:var(--sansFontFamily);font-size:.7rem}.autocomplete-suggestion .header{margin-right:5px}.autocomplete-suggestion .title,.autocomplete-suggestion .description{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}.autocomplete-suggestions a{text-decoration:none!important}.autocomplete-suggestions::-webkit-scrollbar{width:5px;border-radius:7px;flex-shrink:0}.autocomplete-suggestions::-webkit-scrollbar-thumb{background-color:var(--autocompleteSrollbarThumb);border-radius:7px}.autocomplete-suggestions::-webkit-scrollbar-track{background-color:var(--autocompleteSrollbarTrack)}@media screen and (max-width: 1023px){.autocomplete-results .press-return{display:none}}.tooltip{box-shadow:0 0 10px var(--black-opacity-10);max-height:300px;max-width:500px;padding:0;position:absolute;pointer-events:none;margin:0;z-index:99;top:0;left:0;visibility:hidden;transform:translateY(20px);opacity:0;transition:.2s visibility ease-out,.2s transform ease-out,.2s opacity ease-out}.tooltip.tooltip-shown{visibility:visible;transform:translateY(0);opacity:1}.tooltip .tooltip-body{border:1px solid var(--codeBorder)}.tooltip .tooltip-body .signature{min-width:320px;width:100%}.tooltip .tooltip-body .detail-header{border-left:0;margin-bottom:0;margin-top:0}.tooltip .tooltip-body .docstring{background-color:var(--background);padding:1.2em;margin:0;width:498px}.tooltip .tooltip-body .docstring-plain{max-width:498px;width:auto}.tooltip .tooltip-body .version-info{float:right;line-height:1.6rem;font-family:var(--monoFontFamily);font-size:.9rem;font-weight:400;margin-bottom:-6px;opacity:.3;padding-left:.3em}pre{position:relative}pre:hover .copy-button,pre .copy-button:focus{opacity:1}.copy-button{display:flex;opacity:0;position:absolute;top:5px;right:5px;padding:4px;background-color:var(--codeBackground);border:none;cursor:pointer;transition:all .15s;font-family:var(--defaultFontFamily);font-size:14px;line-height:24px;color:currentColor}.copy-button svg{opacity:.5;transition:all .15s}pre .copy-button:hover svg,pre .copy-button:focus-visible svg{opacity:1}.copy-button svg{width:20px}.copy-button.clicked{opacity:1;color:var(--success)}.copy-button.clicked svg{display:none;color:currentColor}#settings-modal-content{margin-top:10px}#settings-modal-content .hidden{display:none}#settings-modal-content .input{box-sizing:border-box;width:80%;padding:8px;font-size:14px;background-color:var(--settingsInputBackground);color:var(--settingsInput);border:1px solid var(--settingsInputBorder);border-radius:8px;transition:border-color .15s}#settings-modal-content .input:focus{border-color:var(--main)}#settings-modal-content .input::placeholder{color:var(--gray400)}#settings-modal-content .switch-button-container{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--settingsSectionBorder);padding:10px 0}#settings-modal-content .switch-button-container:first-of-type{border-top-style:none;padding-top:0}#settings-modal-content .switch-button-container>div>span{font-size:18px}#settings-modal-content .switch-button-container>div>p{font-size:14px;font-weight:300;line-height:1.4;margin:0;padding-bottom:6px;padding-right:10px}#settings-modal-content .switch-button{position:relative;display:inline-block;flex-shrink:0;width:40px;height:20px;user-select:none;transition:all .15s}#settings-modal-content .switch-button__checkbox{appearance:none;position:absolute;display:block;width:20px;height:20px;border-radius:1000px;background-color:#91a4b7;border:3px solid #e5edf5;cursor:pointer;transition:all .3s}#settings-modal-content .switch-button__bg{display:block;width:100%;height:100%;border-radius:1000px;background-color:#e5edf5;cursor:pointer;transition:all .3s}#settings-modal-content .switch-button__checkbox:checked{background-color:#fff;border-color:var(--main);transform:translate(100%)}#settings-modal-content .switch-button__checkbox:checked+.switch-button__bg{background-color:var(--main)}#settings-modal-content .switch-button__checkbox:focus{outline:0}#settings-modal-content .switch-button__checkbox:focus+.switch-button__bg{outline:2px solid var(--main);outline-offset:2px}#settings-modal-content .switch-button__checkbox:focus:not(:focus-visible)+.switch-button__bg{outline:0}#settings-modal-content .settings-select{cursor:pointer;position:relative;border:none;background-color:transparent;color:var(--textBody)}#settings-modal-content .settings-select option{color:initial}#toast{opacity:0;position:fixed;z-index:1;left:50%;bottom:1rem;min-width:3rem;margin:0 -1.2rem;padding:.7rem 1.2rem;text-align:center;font-weight:700;border-radius:10px;border:1px solid var(--codeBorder);background-color:var(--codeBackground);color:var(--textBody);transition:opacity .4s ease-in-out,transform .3s ease-out;cursor:default}#toast.show{opacity:1;transform:translateY(-.75rem)}@media (prefers-reduced-motion: reduce){#toast{transition:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0;user-select:none}@media print{.body-wrapper{display:block}.sidebar,.sidebar-button,.top-search{display:none}.content{padding-left:0;overflow:visible;left:0;width:100%}.summary-row{break-inside:avoid}#toast{display:none}.content-inner{padding:0}.content-inner .section-heading a.hover-link,.content-inner button.icon-action,.content-inner a.icon-action,.content-inner .bottom-actions{display:none}.footer p:first-of-type{display:none}.content-inner section.admonition{border:2px solid var(--gray400)}.content-inner section.admonition>.admonition-title{color:var(--textHeaders);border-bottom:2px solid var(--gray400)}.content-inner pre code.makeup{border-color:var(--gray400);white-space:break-spaces;break-inside:avoid}.content-inner blockquote code.inline,.content-inner code.inline{border-color:var(--gray400)}}@media print{.page-cheatmd .content-inner *{background-color:transparent!important;border-color:var(--gray400)!important}.page-cheatmd .content-inner{max-width:100%;width:100%;padding:0;font-size:.7em}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:30px}.page-cheatmd .content-inner section.col-2{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:grid}.page-cheatmd .content-inner section.col-3{column-count:3}.page-cheatmd .content-inner h1{margin-top:0;margin-bottom:.5em}.page-cheatmd .content-inner h2.section-heading{font-weight:700;margin-top:1em;column-span:all}.page-cheatmd .content-inner section.h2{break-inside:avoid}.page-cheatmd .content-inner h3{font-weight:700;color:var(--mainDark)}.page-cheatmd .content-inner h3:after{height:2px;background-color:var(--gray400)}.page-cheatmd .content-inner section.h3{min-width:300px;break-inside:avoid}.page-cheatmd .content-inner h4{padding:.5em 0;border:none;font-weight:700;color:#000}.page-cheatmd .content-inner .h2 p{padding-left:0;padding-right:0;border:none!important}.page-cheatmd .content-inner code{line-height:1.5em}.page-cheatmd .content-inner .h2 table{font-variant-numeric:tabular-nums;break-inside:avoid}.page-cheatmd .content-inner .h2 :is(th,td){vertical-align:top;padding-left:0;padding-right:0}.page-cheatmd .content-inner .h2 thead{border-style:solid none;border-width:1px}.page-cheatmd .content-inner .h2 tr{border-bottom:none}.page-cheatmd .content-inner .h2 th{font-weight:700}.page-cheatmd .content-inner .h2 li{padding-left:0;padding-right:0;vertical-align:middle;border-bottom:none}.page-cheatmd .content-inner pre:hover button.copy-button,.page-cheatmd .content-inner div.tooltip{display:none}.page-cheatmd .content-inner footer p:not(.built-using){display:none}}code.makeup .unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.makeup .hll{background-color:#ffc}.makeup .bp{color:#3465a4}.makeup .c,.makeup .c1,.makeup .ch,.makeup .cm,.makeup .cp,.makeup .cpf,.makeup .cs{color:#4d4d4d}.makeup .dl{color:#408200}.makeup .err{color:#a40000;border:#ef2929}.makeup .fm,.makeup .g{color:#4d4d4c}.makeup .gd{color:#a40000}.makeup .ge{color:#4d4d4c;font-style:italic}.makeup .gh{color:navy;font-weight:700}.makeup .gi{color:#00a000}.makeup .go{color:#4d4d4c;font-style:italic}.makeup .gp{color:#4d4d4d}.makeup .gr{color:#ef2929}.makeup .gs{color:#4d4d4c;font-weight:700}.makeup .gt{color:#a40000;font-weight:700}.makeup .gu{color:purple;font-weight:700}.makeup .il{color:#0000cf;font-weight:700}.makeup .k,.makeup .kc,.makeup .kd,.makeup .kn,.makeup .kp,.makeup .kr,.makeup .kt{color:#204a87}.makeup .l{color:#4d4d4c}.makeup .ld{color:#c00}.makeup .m,.makeup .mb,.makeup .mf,.makeup .mh,.makeup .mi,.makeup .mo{color:#2937ab}.makeup .n{color:#4d4d4c}.makeup .na{color:#8a7000}.makeup .nb{color:#204a87}.makeup .nc{color:#0000cf}.makeup .nd{color:#5c35cc;font-weight:700}.makeup .ne{color:#c00;font-weight:700}.makeup .nf{color:#b65800}.makeup .ni{color:#bc5400}.makeup .nl{color:#b65800}.makeup .nn{color:#4d4d4c}.makeup .no{color:#a06600}.makeup .nt{color:#204a87;font-weight:700}.makeup .nv,.makeup .nx{color:#4d4d4c}.makeup .o{color:#bc5400}.makeup .ow{color:#204a87}.makeup .p,.makeup .py{color:#4d4d4c}.makeup .s,.makeup .s1,.makeup .s2,.makeup .sa,.makeup .sb,.makeup .sc{color:#408200}.makeup .sd{color:#8f5902;font-style:italic}.makeup .se{color:#204a87}.makeup .sh{color:#408200}.makeup .si{color:#204a87}.makeup .sr{color:#c00}.makeup .ss{color:#a06600}.makeup .sx{color:#408200}.makeup .vc,.makeup .vg,.makeup .vi,.makeup .vm,.makeup .x{color:#4d4d4c}.dark .makeup{color:#dce1e6}.dark .makeup .hll{background-color:#49483e}.dark .makeup .bp{color:#dce1e6}.dark .makeup .c,.dark .makeup .c1,.dark .makeup .ch,.dark .makeup .cm,.dark .makeup .cp,.dark .makeup .cpf,.dark .makeup .cs{color:#969386}.dark .makeup .dl{color:#e6db74}.dark .makeup .err{color:#960050;background-color:#1e0010}.dark .makeup .fm{color:#a6e22e}.dark .makeup .gd{color:#ff5385}.dark .makeup .ge{font-style:italic}.dark .makeup .gi{color:#a6e22e}.dark .makeup .gp{color:#969386}.dark .makeup .gs{font-weight:700}.dark .makeup .gu{color:#969386}.dark .makeup .gt{color:#ff5385;font-weight:700}.dark .makeup .il{color:#ae81ff}.dark .makeup .k,.dark .makeup .kc,.dark .makeup .kd{color:#66d9ef}.dark .makeup .kn{color:#ff5385}.dark .makeup .kp,.dark .makeup .kr,.dark .makeup .kt{color:#66d9ef}.dark .makeup .l,.dark .makeup .ld,.dark .makeup .m,.dark .makeup .mb,.dark .makeup .mf,.dark .makeup .mh,.dark .makeup .mi,.dark .makeup .mo{color:#ae81ff}.dark .makeup .n{color:#dce1e6}.dark .makeup .na{color:#a6e22e}.dark .makeup .nb{color:#dce1e6}.dark .makeup .nc,.dark .makeup .nd,.dark .makeup .ne,.dark .makeup .nf{color:#a6e22e}.dark .makeup .ni,.dark .makeup .nl,.dark .makeup .nn{color:#dce1e6}.dark .makeup .no{color:#66d9ef}.dark .makeup .nt{color:#ff5385}.dark .makeup .nv{color:#dce1e6}.dark .makeup .nx{color:#a6e22e}.dark .makeup .o,.dark .makeup .ow{color:#ff5385}.dark .makeup .p,.dark .makeup .py{color:#dce1e6}.dark .makeup .s,.dark .makeup .s1,.dark .makeup .s2,.dark .makeup .sa,.dark .makeup .sb,.dark .makeup .sc,.dark .makeup .sd{color:#e6db74}.dark .makeup .se{color:#ae81ff}.dark .makeup .sh,.dark .makeup .si,.dark .makeup .sr,.dark .makeup .ss,.dark .makeup .sx{color:#e6db74}.dark .makeup .vc,.dark .makeup .vg,.dark .makeup .vi,.dark .makeup .vm{color:#dce1e6}.tabset{--borderWidth: 1px;--tabsetPadding: var(--baseLineHeight);margin:var(--baseLineHeight) 0}.tabset-tablist{display:flex;overflow-x:auto}.tabset-tab{padding:.6rem var(--tabsetPadding);min-height:46px;font-family:var(--sansFontFamily);background-color:var(--tabBackground);color:var(--tab);border:var(--borderWidth) solid var(--tabBorder);margin-right:calc(-1 * var(--borderWidth));border-top-width:4px;border-top-color:var(--tabBorderTop);border-radius:0;border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius);box-shadow:0 -3px 4px var(--tabShadow) inset;cursor:pointer}.tabset-tab[aria-selected=true]{border-bottom-color:var(--tabBackground);border-top-color:var(--mainLight);box-shadow:none}.tabset-tab[aria-selected=true]:focus-visible{background-color:var(--mainLight);border-color:var(--mainLight);color:var(--white)}.tabset-panel{padding:0 var(--tabsetPadding);border:var(--borderWidth) solid var(--tabBorder);margin-top:calc(-1 * var(--borderWidth));border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius)}@media screen and (max-width: 768px){.tabset{--tabsetPadding: calc(var(--baseLineHeight) / 2)}.tabset-panel{padding-top:calc(var(--tabsetPadding) / 2);padding-bottom:calc(var(--tabsetPadding) / 2)}.tabset-panel pre,.tabset-panel blockquote,.tabset-panel section.admonition{margin-left:calc(-1 * var(--tabsetPadding))!important;margin-right:calc(-1 * var(--tabsetPadding))!important}.tabset-panel>pre code{border-left-width:0;border-right-width:0}}body.preview{--sidebarWidth: 0px;overflow:hidden}body.preview .content{height:auto}body.preview .content-inner{padding:0}body.preview .sidebar,body.preview #sidebar-menu,body.preview .hover-link,body.preview .detail-link{display:none}body.preview :is(h1,h2,h3):first-of-type{margin-top:0}body:not(.dark) .content-inner img[src*="#gh-dark-mode-only"],body.dark .content-inner img[src*="#gh-light-mode-only"]{display:none} +/*! Bundled license information: + +normalize.css/normalize.css: + (*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css *) +*/ diff --git a/doc/dist/inconsolata-latin-400-normal-RGKDDNDD.woff2 b/doc/dist/inconsolata-latin-400-normal-RGKDDNDD.woff2 new file mode 100644 index 0000000..6119e59 Binary files /dev/null and b/doc/dist/inconsolata-latin-400-normal-RGKDDNDD.woff2 differ diff --git a/doc/dist/inconsolata-latin-700-normal-DTS2D7TO.woff2 b/doc/dist/inconsolata-latin-700-normal-DTS2D7TO.woff2 new file mode 100644 index 0000000..010da61 Binary files /dev/null and b/doc/dist/inconsolata-latin-700-normal-DTS2D7TO.woff2 differ diff --git a/doc/dist/inconsolata-latin-ext-400-normal-K7HVGTP7.woff2 b/doc/dist/inconsolata-latin-ext-400-normal-K7HVGTP7.woff2 new file mode 100644 index 0000000..50cb547 Binary files /dev/null and b/doc/dist/inconsolata-latin-ext-400-normal-K7HVGTP7.woff2 differ diff --git a/doc/dist/inconsolata-latin-ext-700-normal-4MPBLFZC.woff2 b/doc/dist/inconsolata-latin-ext-700-normal-4MPBLFZC.woff2 new file mode 100644 index 0000000..8a20d54 Binary files /dev/null and b/doc/dist/inconsolata-latin-ext-700-normal-4MPBLFZC.woff2 differ diff --git a/doc/dist/inconsolata-vietnamese-400-normal-IGQPHHJH.woff2 b/doc/dist/inconsolata-vietnamese-400-normal-IGQPHHJH.woff2 new file mode 100644 index 0000000..ab70f18 Binary files /dev/null and b/doc/dist/inconsolata-vietnamese-400-normal-IGQPHHJH.woff2 differ diff --git a/doc/dist/inconsolata-vietnamese-700-normal-LHEGSN35.woff2 b/doc/dist/inconsolata-vietnamese-700-normal-LHEGSN35.woff2 new file mode 100644 index 0000000..a814008 Binary files /dev/null and b/doc/dist/inconsolata-vietnamese-700-normal-LHEGSN35.woff2 differ diff --git a/doc/dist/lato-latin-300-normal-YUMVEFOL.woff2 b/doc/dist/lato-latin-300-normal-YUMVEFOL.woff2 new file mode 100644 index 0000000..aad98a3 Binary files /dev/null and b/doc/dist/lato-latin-300-normal-YUMVEFOL.woff2 differ diff --git a/doc/dist/lato-latin-400-normal-W7754I4D.woff2 b/doc/dist/lato-latin-400-normal-W7754I4D.woff2 new file mode 100644 index 0000000..ff60934 Binary files /dev/null and b/doc/dist/lato-latin-400-normal-W7754I4D.woff2 differ diff --git a/doc/dist/lato-latin-700-normal-2XVSBPG4.woff2 b/doc/dist/lato-latin-700-normal-2XVSBPG4.woff2 new file mode 100644 index 0000000..11de83f Binary files /dev/null and b/doc/dist/lato-latin-700-normal-2XVSBPG4.woff2 differ diff --git a/doc/dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 b/doc/dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 new file mode 100644 index 0000000..486d3ec Binary files /dev/null and b/doc/dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 differ diff --git a/doc/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 b/doc/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 new file mode 100644 index 0000000..edb9fa6 Binary files /dev/null and b/doc/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 differ diff --git a/doc/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 b/doc/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 new file mode 100644 index 0000000..2c8aaa8 Binary files /dev/null and b/doc/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 differ diff --git a/doc/dist/remixicon-NKANDIL5.woff2 b/doc/dist/remixicon-NKANDIL5.woff2 new file mode 100644 index 0000000..57e6c7c Binary files /dev/null and b/doc/dist/remixicon-NKANDIL5.woff2 differ diff --git a/doc/dist/search_data-3FEDF90C.js b/doc/dist/search_data-3FEDF90C.js new file mode 100644 index 0000000..bed5040 --- /dev/null +++ b/doc/dist/search_data-3FEDF90C.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","title":"ringbuffer","doc":"Ringbuffer implements a length limited queue. In systems this is often implemented as a ring, or cylic, buffer. Where the writer can push the reader ahead if the buffer is full. This kind of buffers is useful in situations where you can have surges of writers, with a limited amount of readers. And where it is allowed to drop entries from the queue if the readers can't keep up with the writers. An example is a logging system for a http server, which can handle large bursts of requests. The logger is often limited in its throughput, and it is perfectly ok to drop log entries if that means that the server can handle the peak load. This ring buffer is technically not a ring. It is a size limited buffer, implemented in ets. Its main characteristics are: Optimized for writes: non locking and non blocking queue writes; Size limited, define the maximum number of entries upon queue creation; Readers are synchronized to prevent race conditions; Readers return the number of entries that were lost due to too fast writers; As many queues as needed.","ref":"ringbuffer.html"},{"type":"function","title":"ringbuffer.delete/1","doc":"Delete a named ringbuffer, all queued data is destroyed. The ets table and the synchronizing process are deleted.","ref":"ringbuffer.html#delete/1"},{"type":"function","title":"ringbuffer.new/2","doc":"Create a new named buffer of Size entries. The name must be unique for all ets tables. The name must be an atom, and is used for the name of the ets table. A process owning the ets table and synchronizing the readers is added to <tt>ringbuffer_sup</tt>.","ref":"ringbuffer.html#new/2"},{"type":"function","title":"ringbuffer.read/1","doc":"Read the next entry from the named ringbuffer. Return the number of skipped entries and the payload of the entry read. An entry is skipped if the readers are falling behind the writers by more that the size of the buffer. <tt>{error, empty}</tt> is returned if the buffer is empty.","ref":"ringbuffer.html#read/1"},{"type":"function","title":"ringbuffer.start/0","doc":null,"ref":"ringbuffer.html#start/0"},{"type":"function","title":"ringbuffer.whereis/1","doc":"Find the ringbuffer with a certain name, return the pid if found, otherwise undefined.","ref":"ringbuffer.html#whereis/1"},{"type":"function","title":"ringbuffer.write/2","doc":"Add an entry to the named ringbuffer. Never fails, if the ringbuffer is full then older entries are overwritten.","ref":"ringbuffer.html#write/2"},{"type":"type","title":"ringbuffer.ringbuffer/0","doc":null,"ref":"ringbuffer.html#t:ringbuffer/0"},{"type":"module","title":"ringbuffer_app","doc":"RingBuffer application","ref":"ringbuffer_app.html"},{"type":"function","title":"ringbuffer_app.start/2","doc":"Application callback, start the ringbuffer supervisor.","ref":"ringbuffer_app.html#start/2"},{"type":"function","title":"ringbuffer_app.stop/1","doc":"Application callback, called when stopping the application.","ref":"ringbuffer_app.html#stop/1"},{"type":"module","title":"ringbuffer_process","doc":"Process to own the created ets table for the ring buffer.","ref":"ringbuffer_process.html"},{"type":"function","title":"ringbuffer_process.code_change/3","doc":null,"ref":"ringbuffer_process.html#code_change/3"},{"type":"function","title":"ringbuffer_process.handle_call/3","doc":null,"ref":"ringbuffer_process.html#handle_call/3"},{"type":"function","title":"ringbuffer_process.handle_cast/2","doc":null,"ref":"ringbuffer_process.html#handle_cast/2"},{"type":"function","title":"ringbuffer_process.handle_info/2","doc":null,"ref":"ringbuffer_process.html#handle_info/2"},{"type":"function","title":"ringbuffer_process.init/1","doc":null,"ref":"ringbuffer_process.html#init/1"},{"type":"function","title":"ringbuffer_process.process_pid/1","doc":"Find the process pid for the process owning the ets table. If the buffer does not exist then an error is returned.","ref":"ringbuffer_process.html#process_pid/1"},{"type":"function","title":"ringbuffer_process.read/1","doc":"Read a payload from the buffer. Skip entries that are deleted by the writers. There are a coupe of race conditions we need to take care of: 1. Writer incremented -> Reader tries entry --> Writer writes entry In this case the w-value read by the reader is Size smaller than that of the writer. In this case we wait till the writer finishes writing. 2. Two or more readers arrive at the same time, incrementing the reader value. One of the readers will have the correct value and can fetch the next entry. In this case the reader can move past the writer if there are not enough entries in the buffer for all readers. For the case where multiple readers are racing past the writer can not be solved without synchronization, we let the ringbuffer process handle the reader increment.","ref":"ringbuffer_process.html#read/1"},{"type":"function","title":"ringbuffer_process.start_link/2","doc":"Create a new process managing a ringbuffer.","ref":"ringbuffer_process.html#start_link/2"},{"type":"function","title":"ringbuffer_process.terminate/2","doc":null,"ref":"ringbuffer_process.html#terminate/2"},{"type":"function","title":"ringbuffer_process.write/2","doc":"Write a payload the buffer. If the readers can't keep up then older entries are deleted.","ref":"ringbuffer_process.html#write/2"},{"type":"module","title":"ringbuffer_sup","doc":"Supervisor for the ring buffers processes.","ref":"ringbuffer_sup.html"},{"type":"function","title":"ringbuffer_sup.find_child/1","doc":"Find the Pid of the ringbuffer with a certain name.","ref":"ringbuffer_sup.html#find_child/1"},{"type":"function","title":"ringbuffer_sup.init/1","doc":"Supervisor callback, initialize the children.","ref":"ringbuffer_sup.html#init/1"},{"type":"function","title":"ringbuffer_sup.start_child/2","doc":"Start a ringbuffer.","ref":"ringbuffer_sup.html#start_child/2"},{"type":"function","title":"ringbuffer_sup.start_link/0","doc":"Start the simple_one_for_one supervisor for the ring buffer processes.","ref":"ringbuffer_sup.html#start_link/0"},{"type":"function","title":"ringbuffer_sup.stop_child/1","doc":"Stop a ringbuffer. The managing process is removed from the supervisor and the ets table is released.","ref":"ringbuffer_sup.html#stop_child/1"},{"type":"extras","title":"Overview","doc":"[![Test](https://github.com/zotonic/ringbuffer/workflows/Test/badge.svg)](https://github.com/zotonic/ringbuffer/actions?query=workflow%3ATest)\n[![Hex version](https://img.shields.io/hexpm/v/ringbuffer.svg \"Hex version\")](https://hex.pm/packages/ringbuffer)\n\nRingbuffer\n==========\n\nA ring buffer implementation using Erlang and ets tables.\n\nMain feature is lock free writing without message passing, making\nthis implementation ideal for log systems with many fast writers or\nbig bursts.\n\nRingbuffer implements a length limited queue. In systems this is\noften implemented as a ring, or cylic, buffer. Where the writer can\npush the reader ahead if the buffer is full.\n\nThis kind of buffers is useful in situations where you can have\nsurges of writers, with a limited amount of readers. And where it\nis allowed to drop entries from the queue if the readers can't keep\nup with the writers.\n\nAn example is a logging system for a http server, which can handle large\nbursts of requests. The logger is often limited in its throughput, and it\nis perfectly ok to drop log entries if that means that the server can\nhandle the peak load.\n\nThis ring buffer is technically not a ring. It is a size limited buffer,\nimplemented in ets. Its main characteristics are:\n\n * Optimized for writes: non locking and non blocking queue writes;\n * Size limited, define the maximum number of entries upon queue creation;\n * Readers are synchronized to prevent race conditions;\n * Readers return the number of entries that were lost due to too fast writers;\n * As many queues as needed.\n\nThe size of the ring is set upon creation. If the ring is full\nthen older entries are overwritten. Overwritten entries are skipped\nwhen reading the next entry. The number of skipped entries is\nreturned.\n\nThe ring's ets table is owned by a process managed by the ringbuffer_sup.","ref":"readme.html"},{"type":"extras","title":"Installation - Overview","doc":"RingBuffer is at Hex, in your `rebar.config` file use:\n\n```erlang\n{deps, [\n ringbuffer\n]}.\n```\n\nYou can also use the direct Git url and use the development version:\n\n```erlang\n{deps, [\n {ringbuffer, {git, \"https://github.com/zotonic/ringbuffer.git\", {branch, \"main\"}}}\n]}.\n```","ref":"readme.html#installation"},{"type":"extras","title":"Usage - Overview","doc":"First create a ringbuffer. The buffer is named with an atom\nand needs a size of the maximum amount of items to buffer.\n\n```erlang\n {ok, Pid} = ringbuffer:new(name, 1000)\n```\n\nThen an entry can be written:\n\n```erlang\n ok = ringbuffer:write(name, Payload).\n```\n\nThe `Payload` can be any Erlang term.\n\n\nIt can be read afterwards:\n\n```erlang\n {ok, {NSkipped, Payload}} = ringbuffer:read(name).\n```\n\nThe `NSkipped` is the number of entries skipped during reads. If the consumer\ncan keep up with the producers then it will be `0`. If entries are overwritten\nthen it will return the number of overwritten entries.\n\nIf the buffer is empty then an error is returned:\n\n```erlang\n {error, empty} = ringbuffer:read(name).\n```","ref":"readme.html#usage"},{"type":"extras","title":"Use in your own supervisor - Overview","doc":"You can use ringbuffer in your own supervisor with the following child spec:\n\n```erlang\n % Size and name of the ringbuffer\n BufferSize = 1000,\n NameOfMyBuffer = foobar,\n % The child spec for your supervisor\n #{\n start => {ringbuffer_process, start_link, [NameOfMyBuffer, BufferSize]},\n restart => permanent,\n type => worker\n }\n```","ref":"readme.html#use-in-your-own-supervisor"},{"type":"extras","title":"Test - Overview","doc":"Run the tests:\n\n```\nmake test\n```\n\nAll tests should pass.\n\nFor additional checks, also run:\n\n```\nmake xref\nmake dialyzer\n```","ref":"readme.html#test"},{"type":"extras","title":"License - Overview","doc":"Ringbuffer is licensed under the Apache 2.0 license.","ref":"readme.html#license"},{"type":"extras","title":"License","doc":"Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.","ref":"license.html"}],"proglang":"erlang","content_type":"text/markdown","producer":{"name":"ex_doc","version":"0.35.1"}} \ No newline at end of file diff --git a/doc/dist/sidebar_items-C002F7F1.js b/doc/dist/sidebar_items-C002F7F1.js new file mode 100644 index 0000000..c416d37 --- /dev/null +++ b/doc/dist/sidebar_items-C002F7F1.js @@ -0,0 +1 @@ +sidebarNodes={"modules":[{"id":"ringbuffer","deprecated":false,"group":"","title":"ringbuffer","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"ringbuffer/0","deprecated":false,"title":"ringbuffer/0","anchor":"t:ringbuffer/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"delete/1","deprecated":false,"title":"delete(Name)","anchor":"delete/1"},{"id":"new/2","deprecated":false,"title":"new(Name, Size)","anchor":"new/2"},{"id":"read/1","deprecated":false,"title":"read(Name)","anchor":"read/1"},{"id":"start/0","deprecated":false,"title":"start()","anchor":"start/0"},{"id":"whereis/1","deprecated":false,"title":"whereis(Name)","anchor":"whereis/1"},{"id":"write/2","deprecated":false,"title":"write(Name, Payload)","anchor":"write/2"}],"key":"functions"}]},{"id":"ringbuffer_app","deprecated":false,"group":"","title":"ringbuffer_app","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"start/2","deprecated":false,"title":"start(StartType, StartArgs)","anchor":"start/2"},{"id":"stop/1","deprecated":false,"title":"stop(State)","anchor":"stop/1"}],"key":"functions"}]},{"id":"ringbuffer_process","deprecated":false,"group":"","title":"ringbuffer_process","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"code_change/3","deprecated":false,"title":"code_change(OldVsn, State, Extra)","anchor":"code_change/3"},{"id":"handle_call/3","deprecated":false,"title":"handle_call(_, From, State)","anchor":"handle_call/3"},{"id":"handle_cast/2","deprecated":false,"title":"handle_cast(Msg, State)","anchor":"handle_cast/2"},{"id":"handle_info/2","deprecated":false,"title":"handle_info(Info, State)","anchor":"handle_info/2"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"process_pid/1","deprecated":false,"title":"process_pid(Name)","anchor":"process_pid/1"},{"id":"read/1","deprecated":false,"title":"read(Name)","anchor":"read/1"},{"id":"start_link/2","deprecated":false,"title":"start_link(Name, Size)","anchor":"start_link/2"},{"id":"terminate/2","deprecated":false,"title":"terminate(Reason, State)","anchor":"terminate/2"},{"id":"write/2","deprecated":false,"title":"write(Name, Payload)","anchor":"write/2"}],"key":"functions"}]},{"id":"ringbuffer_sup","deprecated":false,"group":"","title":"ringbuffer_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"find_child/1","deprecated":false,"title":"find_child(Name)","anchor":"find_child/1"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_child/2","deprecated":false,"title":"start_child(Name, Size)","anchor":"start_child/2"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"},{"id":"stop_child/1","deprecated":false,"title":"stop_child(Name)","anchor":"stop_child/1"}],"key":"functions"}]}],"extras":[{"id":"api-reference","group":"","title":"API Reference","headers":[{"id":"Modules","anchor":"modules"}]},{"id":"readme","group":"","title":"Overview","headers":[{"id":"Installation","anchor":"installation"},{"id":"Usage","anchor":"usage"},{"id":"Use in your own supervisor","anchor":"use-in-your-own-supervisor"},{"id":"Test","anchor":"test"},{"id":"License","anchor":"license"}]},{"id":"license","group":"","title":"License","headers":[]}],"tasks":[]} \ No newline at end of file diff --git a/doc/index.html b/doc/index.html index d7ad9ba..1c8f793 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,17 +1,10 @@ - + - -The ringbuffer application - - - - - - -<h2>This page uses frames</h2> -<p>Your browser does not accept frames. -<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead. -</p> - - - \ No newline at end of file + + + ringbuffer v1.2.0+build.18.refca920a0 — Documentation + + + + + diff --git a/doc/license.html b/doc/license.html new file mode 100644 index 0000000..1abef3a --- /dev/null +++ b/doc/license.html @@ -0,0 +1,385 @@ + + + + + + + + + + + License — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + + License +

    + +
    +
    +                              Apache License
    +                        Version 2.0, January 2004
    +                     http://www.apache.org/licenses/
    +
    +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
    +
    +1. Definitions.
    +
    +   "License" shall mean the terms and conditions for use, reproduction,
    +   and distribution as defined by Sections 1 through 9 of this document.
    +
    +   "Licensor" shall mean the copyright owner or entity authorized by
    +   the copyright owner that is granting the License.
    +
    +   "Legal Entity" shall mean the union of the acting entity and all
    +   other entities that control, are controlled by, or are under common
    +   control with that entity. For the purposes of this definition,
    +   "control" means (i) the power, direct or indirect, to cause the
    +   direction or management of such entity, whether by contract or
    +   otherwise, or (ii) ownership of fifty percent (50%) or more of the
    +   outstanding shares, or (iii) beneficial ownership of such entity.
    +
    +   "You" (or "Your") shall mean an individual or Legal Entity
    +   exercising permissions granted by this License.
    +
    +   "Source" form shall mean the preferred form for making modifications,
    +   including but not limited to software source code, documentation
    +   source, and configuration files.
    +
    +   "Object" form shall mean any form resulting from mechanical
    +   transformation or translation of a Source form, including but
    +   not limited to compiled object code, generated documentation,
    +   and conversions to other media types.
    +
    +   "Work" shall mean the work of authorship, whether in Source or
    +   Object form, made available under the License, as indicated by a
    +   copyright notice that is included in or attached to the work
    +   (an example is provided in the Appendix below).
    +
    +   "Derivative Works" shall mean any work, whether in Source or Object
    +   form, that is based on (or derived from) the Work and for which the
    +   editorial revisions, annotations, elaborations, or other modifications
    +   represent, as a whole, an original work of authorship. For the purposes
    +   of this License, Derivative Works shall not include works that remain
    +   separable from, or merely link (or bind by name) to the interfaces of,
    +   the Work and Derivative Works thereof.
    +
    +   "Contribution" shall mean any work of authorship, including
    +   the original version of the Work and any modifications or additions
    +   to that Work or Derivative Works thereof, that is intentionally
    +   submitted to Licensor for inclusion in the Work by the copyright owner
    +   or by an individual or Legal Entity authorized to submit on behalf of
    +   the copyright owner. For the purposes of this definition, "submitted"
    +   means any form of electronic, verbal, or written communication sent
    +   to the Licensor or its representatives, including but not limited to
    +   communication on electronic mailing lists, source code control systems,
    +   and issue tracking systems that are managed by, or on behalf of, the
    +   Licensor for the purpose of discussing and improving the Work, but
    +   excluding communication that is conspicuously marked or otherwise
    +   designated in writing by the copyright owner as "Not a Contribution."
    +
    +   "Contributor" shall mean Licensor and any individual or Legal Entity
    +   on behalf of whom a Contribution has been received by Licensor and
    +   subsequently incorporated within the Work.
    +
    +2. Grant of Copyright License. Subject to the terms and conditions of
    +   this License, each Contributor hereby grants to You a perpetual,
    +   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    +   copyright license to reproduce, prepare Derivative Works of,
    +   publicly display, publicly perform, sublicense, and distribute the
    +   Work and such Derivative Works in Source or Object form.
    +
    +3. Grant of Patent License. Subject to the terms and conditions of
    +   this License, each Contributor hereby grants to You a perpetual,
    +   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    +   (except as stated in this section) patent license to make, have made,
    +   use, offer to sell, sell, import, and otherwise transfer the Work,
    +   where such license applies only to those patent claims licensable
    +   by such Contributor that are necessarily infringed by their
    +   Contribution(s) alone or by combination of their Contribution(s)
    +   with the Work to which such Contribution(s) was submitted. If You
    +   institute patent litigation against any entity (including a
    +   cross-claim or counterclaim in a lawsuit) alleging that the Work
    +   or a Contribution incorporated within the Work constitutes direct
    +   or contributory patent infringement, then any patent licenses
    +   granted to You under this License for that Work shall terminate
    +   as of the date such litigation is filed.
    +
    +4. Redistribution. You may reproduce and distribute copies of the
    +   Work or Derivative Works thereof in any medium, with or without
    +   modifications, and in Source or Object form, provided that You
    +   meet the following conditions:
    +
    +   (a) You must give any other recipients of the Work or
    +       Derivative Works a copy of this License; and
    +
    +   (b) You must cause any modified files to carry prominent notices
    +       stating that You changed the files; and
    +
    +   (c) You must retain, in the Source form of any Derivative Works
    +       that You distribute, all copyright, patent, trademark, and
    +       attribution notices from the Source form of the Work,
    +       excluding those notices that do not pertain to any part of
    +       the Derivative Works; and
    +
    +   (d) If the Work includes a "NOTICE" text file as part of its
    +       distribution, then any Derivative Works that You distribute must
    +       include a readable copy of the attribution notices contained
    +       within such NOTICE file, excluding those notices that do not
    +       pertain to any part of the Derivative Works, in at least one
    +       of the following places: within a NOTICE text file distributed
    +       as part of the Derivative Works; within the Source form or
    +       documentation, if provided along with the Derivative Works; or,
    +       within a display generated by the Derivative Works, if and
    +       wherever such third-party notices normally appear. The contents
    +       of the NOTICE file are for informational purposes only and
    +       do not modify the License. You may add Your own attribution
    +       notices within Derivative Works that You distribute, alongside
    +       or as an addendum to the NOTICE text from the Work, provided
    +       that such additional attribution notices cannot be construed
    +       as modifying the License.
    +
    +   You may add Your own copyright statement to Your modifications and
    +   may provide additional or different license terms and conditions
    +   for use, reproduction, or distribution of Your modifications, or
    +   for any such Derivative Works as a whole, provided Your use,
    +   reproduction, and distribution of the Work otherwise complies with
    +   the conditions stated in this License.
    +
    +5. Submission of Contributions. Unless You explicitly state otherwise,
    +   any Contribution intentionally submitted for inclusion in the Work
    +   by You to the Licensor shall be under the terms and conditions of
    +   this License, without any additional terms or conditions.
    +   Notwithstanding the above, nothing herein shall supersede or modify
    +   the terms of any separate license agreement you may have executed
    +   with Licensor regarding such Contributions.
    +
    +6. Trademarks. This License does not grant permission to use the trade
    +   names, trademarks, service marks, or product names of the Licensor,
    +   except as required for reasonable and customary use in describing the
    +   origin of the Work and reproducing the content of the NOTICE file.
    +
    +7. Disclaimer of Warranty. Unless required by applicable law or
    +   agreed to in writing, Licensor provides the Work (and each
    +   Contributor provides its Contributions) on an "AS IS" BASIS,
    +   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    +   implied, including, without limitation, any warranties or conditions
    +   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
    +   PARTICULAR PURPOSE. You are solely responsible for determining the
    +   appropriateness of using or redistributing the Work and assume any
    +   risks associated with Your exercise of permissions under this License.
    +
    +8. Limitation of Liability. In no event and under no legal theory,
    +   whether in tort (including negligence), contract, or otherwise,
    +   unless required by applicable law (such as deliberate and grossly
    +   negligent acts) or agreed to in writing, shall any Contributor be
    +   liable to You for damages, including any direct, indirect, special,
    +   incidental, or consequential damages of any character arising as a
    +   result of this License or out of the use or inability to use the
    +   Work (including but not limited to damages for loss of goodwill,
    +   work stoppage, computer failure or malfunction, or any and all
    +   other commercial damages or losses), even if such Contributor
    +   has been advised of the possibility of such damages.
    +
    +9. Accepting Warranty or Additional Liability. While redistributing
    +   the Work or Derivative Works thereof, You may choose to offer,
    +   and charge a fee for, acceptance of support, warranty, indemnity,
    +   or other liability obligations and/or rights consistent with this
    +   License. However, in accepting such obligations, You may act only
    +   on Your own behalf and on Your sole responsibility, not on behalf
    +   of any other Contributor, and only if You agree to indemnify,
    +   defend, and hold each Contributor harmless for any liability
    +   incurred by, or claims asserted against, such Contributor by reason
    +   of your accepting any such warranty or additional liability.
    +
    +END OF TERMS AND CONDITIONS
    +
    +APPENDIX: How to apply the Apache License to your work.
    +
    +   To apply the Apache License to your work, attach the following
    +   boilerplate notice, with the fields enclosed by brackets "[]"
    +   replaced with your own identifying information. (Don't include
    +   the brackets!)  The text should be enclosed in the appropriate
    +   comment syntax for the file format. We also recommend that a
    +   file or class name and description of purpose be included on the
    +   same "printed page" as the copyright notice for easier
    +   identification within third-party archives.
    +
    +Copyright [yyyy] [name of copyright owner]
    +
    +Licensed under the Apache License, Version 2.0 (the "License");
    +you may not use this file except in compliance with the License.
    +You may obtain a copy of the License at
    +
    +    http://www.apache.org/licenses/LICENSE-2.0
    +
    +Unless required by applicable law or agreed to in writing, software
    +distributed under the License is distributed on an "AS IS" BASIS,
    +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +See the License for the specific language governing permissions and
    +limitations under the License.
    +
    +
    + + + +
    +
    +
    + + + diff --git a/doc/modules-frame.html b/doc/modules-frame.html index c9e586f..af516e5 100644 --- a/doc/modules-frame.html +++ b/doc/modules-frame.html @@ -2,7 +2,7 @@ The ringbuffer application - +

    Modules

    diff --git a/doc/overview-summary.html b/doc/overview-summary.html index 71be72f..f924942 100644 --- a/doc/overview-summary.html +++ b/doc/overview-summary.html @@ -3,7 +3,7 @@ The ringbuffer application - + diff --git a/doc/readme.html b/doc/readme.html new file mode 100644 index 0000000..f540ac2 --- /dev/null +++ b/doc/readme.html @@ -0,0 +1,252 @@ + + + + + + + + + + + Overview — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + + Overview +

    + +

    Test +Hex version

    Ringbuffer

    A ring buffer implementation using Erlang and ets tables.

    Main feature is lock free writing without message passing, making +this implementation ideal for log systems with many fast writers or +big bursts.

    Ringbuffer implements a length limited queue. In systems this is +often implemented as a ring, or cylic, buffer. Where the writer can +push the reader ahead if the buffer is full.

    This kind of buffers is useful in situations where you can have +surges of writers, with a limited amount of readers. And where it +is allowed to drop entries from the queue if the readers can't keep +up with the writers.

    An example is a logging system for a http server, which can handle large +bursts of requests. The logger is often limited in its throughput, and it +is perfectly ok to drop log entries if that means that the server can +handle the peak load.

    This ring buffer is technically not a ring. It is a size limited buffer, +implemented in ets. Its main characteristics are:

    • Optimized for writes: non locking and non blocking queue writes;
    • Size limited, define the maximum number of entries upon queue creation;
    • Readers are synchronized to prevent race conditions;
    • Readers return the number of entries that were lost due to too fast writers;
    • As many queues as needed.

    The size of the ring is set upon creation. If the ring is full +then older entries are overwritten. Overwritten entries are skipped +when reading the next entry. The number of skipped entries is +returned.

    The ring's ets table is owned by a process managed by the ringbuffer_sup.

    + + + + Installation +

    +

    RingBuffer is at Hex, in your rebar.config file use:

    {deps, [
    +    ringbuffer
    +]}.

    You can also use the direct Git url and use the development version:

    {deps, [
    +    {ringbuffer, {git, "https://github.com/zotonic/ringbuffer.git", {branch, "main"}}}
    +]}.

    + + + + Usage +

    +

    First create a ringbuffer. The buffer is named with an atom +and needs a size of the maximum amount of items to buffer.

        {ok, Pid} = ringbuffer:new(name, 1000)

    Then an entry can be written:

        ok = ringbuffer:write(name, Payload).

    The Payload can be any Erlang term.

    It can be read afterwards:

        {ok, {NSkipped, Payload}} = ringbuffer:read(name).

    The NSkipped is the number of entries skipped during reads. If the consumer +can keep up with the producers then it will be 0. If entries are overwritten +then it will return the number of overwritten entries.

    If the buffer is empty then an error is returned:

        {error, empty} = ringbuffer:read(name).

    + + + + Use in your own supervisor +

    +

    You can use ringbuffer in your own supervisor with the following child spec:

        % Size and name of the ringbuffer
    +    BufferSize = 1000,
    +    NameOfMyBuffer = foobar,
    +    % The child spec for your supervisor
    +    #{
    +        start => {ringbuffer_process, start_link, [NameOfMyBuffer, BufferSize]},
    +        restart => permanent,
    +        type => worker
    +    }

    + + + + Test +

    +

    Run the tests:

    make test

    All tests should pass.

    For additional checks, also run:

    make xref
    +make dialyzer

    + + + + License +

    +

    Ringbuffer is licensed under the Apache 2.0 license.

    +
    + + + +
    +
    +
    + + + diff --git a/doc/ringbuffer.epub b/doc/ringbuffer.epub new file mode 100644 index 0000000..d27edb8 Binary files /dev/null and b/doc/ringbuffer.epub differ diff --git a/doc/ringbuffer.html b/doc/ringbuffer.html index 239c2b9..97fefec 100644 --- a/doc/ringbuffer.html +++ b/doc/ringbuffer.html @@ -1,101 +1,459 @@ - - - - -Module ringbuffer - - - - -
    - -

    Module ringbuffer

    -Ringbuffer implements a length limited queue. -

    Copyright © 2021 Marc Worrell

    - -

    Authors: Marc Worrell (marc@worrell.nl).

    - -

    Description

    Ringbuffer implements a length limited queue. In systems this is -often implemented as a ring, or cylic, buffer. Where the writer can -push the reader ahead if the buffer is full.

    - -

    This kind of buffers is useful in situations where you can have -surges of writers, with a limited amount of readers. And where it -is allowed to drop entries from the queue if the readers can't keep -up with the writers.

    - -

    An example is a logging system for a http server, which can handle large -bursts of requests. The logger is often limited in its throughput, and it -is perfectly ok to drop log entries if that means that the server can -handle the peak load.

    - -

    This ring buffer is technically not a ring. It is a size limited buffer, -implemented in ets. Its main characteristics are:

    - -
      -
    • Optimized for writes: non locking and non blocking queue writes;
    • -
    • Size limited, define the maximum number of entries upon queue creation;
    • -
    • Readers are synchronized to prevent race conditions;
    • -
    • Readers return the number of entries that were lost due to too - fast writers;
    • -
    • As many queues as needed.
    • -
    - -

    Data Types

    - -

    ringbuffer()

    -

    ringbuffer() = term()

    - - -

    Function Index

    - - - - - -
    delete/1Delete a named ringbuffer, all queued data is destroyed.
    new/2Create a new named buffer of Size entries.
    read/1Read the next entry from the named ringbuffer.
    start/0
    write/2Add an entry to the named ringbuffer.
    - -

    Function Details

    - -

    delete/1

    -
    -

    delete(Name::atom()) -> ok | {error, not_found}

    -

    -

    Delete a named ringbuffer, all queued data is destroyed. The ets table and the - synchronizing process are deleted.

    - -

    new/2

    -
    -

    new(Name::atom(), Size::pos_integer()) -> {ok, pid()} | {error, term()}

    -

    -

    Create a new named buffer of Size entries. The name must be unique for all ets tables. - The name must be an atom, and is used for the name of the ets table. A process owning the - ets table and synchronizing the readers is added to ringbuffer_sup.

    - -

    read/1

    -
    -

    read(Name::atom()) -> {ok, {non_neg_integer(), term()}} | {error, empty}

    -

    -

    Read the next entry from the named ringbuffer. Return the number of skipped entries and - the payload of the entry read. An entry is skipped if the readers are falling behind the - writers by more that the size of the buffer. {error, empty} is returned if the - buffer is empty.

    - -

    start/0

    -
    -

    start() -> any()

    -

    + + + + + + + + + + + ringbuffer — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + ringbuffer + (ringbuffer v1.2.0+build.18.refca920a0) + +

    + + +
    +

    Ringbuffer implements a length limited queue. In systems this is often implemented as a ring, or cylic, buffer. Where the writer can push the reader ahead if the buffer is full.

    This kind of buffers is useful in situations where you can have surges of writers, with a limited amount of readers. And where it is allowed to drop entries from the queue if the readers can't keep up with the writers.

    An example is a logging system for a http server, which can handle large bursts of requests. The logger is often limited in its throughput, and it is perfectly ok to drop log entries if that means that the server can handle the peak load.

    This ring buffer is technically not a ring. It is a size limited buffer, implemented in ets. Its main characteristics are:

    • Optimized for writes: non locking and non blocking queue writes;
    • Size limited, define the maximum number of entries upon queue creation;
    • Readers are synchronized to prevent race conditions;
    • Readers return the number of entries that were lost due to too fast writers;
    • As many queues as needed.
    +
    + +
    + +
    +

    + + + + Summary +

    +
    +

    + Types +

    + +
    +
    + ringbuffer/0 + +
    + +
    + +
    +
    +

    + Functions +

    + +
    +
    + delete(Name) + +
    + +

    Delete a named ringbuffer, all queued data is destroyed. The ets table and the synchronizing process are deleted.

    + +
    + +
    + + +

    Create a new named buffer of Size entries. The name must be unique for all ets tables. The name must be an atom, and is used for the name of the ets table. A process owning the ets table and synchronizing the readers is added to <tt>ringbuffer_sup</tt>.

    + +
    + +
    +
    + read(Name) + +
    + +

    Read the next entry from the named ringbuffer. Return the number of skipped entries and the payload of the entry read. An entry is skipped if the readers are falling behind the writers by more that the size of the buffer. <tt>{error, empty}</tt> is returned if the buffer is empty.

    + +
    + +
    +
    + start() + +
    + +
    + +
    + + +

    Find the ringbuffer with a certain name, return the pid if found, otherwise undefined.

    + +
    + +
    + + +

    Add an entry to the named ringbuffer. Never fails, if the ringbuffer is full then older entries are overwritten.

    + +
    + +
    + +
    + + +
    +

    + + + + Types +

    +
    +
    + +
    + + + +

    ringbuffer/0

    + + + + + + +
    + +
    + +
    + +
    -type ringbuffer() :: term().
    + +
    + + +
    +
    + +
    +
    + +
    +

    + + + + Functions +

    +
    +
    + +
    + + + +

    delete(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec delete(Name) -> ok | {error, not_found} when Name :: atom().
    + +
    + +

    Delete a named ringbuffer, all queued data is destroyed. The ets table and the synchronizing process are deleted.

    +
    +
    +
    + +
    + + + +

    new(Name, Size)

    + + + + + + +
    + +
    + +
    + +
    -spec new(Name, Size) -> {ok, pid()} | {error, Reason}
    +             when Name :: atom(), Size :: pos_integer(), Reason :: {already_started, pid()} | term().
    + +
    + +

    Create a new named buffer of Size entries. The name must be unique for all ets tables. The name must be an atom, and is used for the name of the ets table. A process owning the ets table and synchronizing the readers is added to <tt>ringbuffer_sup</tt>.

    +
    +
    +
    + +
    + + + +

    read(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec read(Name) -> {ok, {SkipCount, Payload}} | {error, empty}
    +              when Name :: atom(), SkipCount :: non_neg_integer(), Payload :: term().
    + +
    + +

    Read the next entry from the named ringbuffer. Return the number of skipped entries and the payload of the entry read. An entry is skipped if the readers are falling behind the writers by more that the size of the buffer. <tt>{error, empty}</tt> is returned if the buffer is empty.

    +
    +
    +
    + +
    + + + +

    start()

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    whereis(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec whereis(Name) -> pid() | undefined when Name :: atom().
    + +
    + +

    Find the ringbuffer with a certain name, return the pid if found, otherwise undefined.

    +
    +
    +
    + +
    + + + +

    write(Name, Payload)

    + + + + + + +
    + +
    + +
    + +
    -spec write(Name, Payload) -> ok when Name :: atom(), Payload :: term().
    + +
    + +

    Add an entry to the named ringbuffer. Never fails, if the ringbuffer is full then older entries are overwritten.

    +
    +
    + +
    +
    + + +
    +
    -

    write/2

    -
    -

    write(Name::atom(), Payload::term()) -> ok

    -

    -

    Add an entry to the named ringbuffer. Never fails, if the ringbuffer - is full then older entries are overwritten.

    -
    - - -

    Generated by EDoc

    - + diff --git a/doc/ringbuffer_app.html b/doc/ringbuffer_app.html index f0ca049..b24ee4c 100644 --- a/doc/ringbuffer_app.html +++ b/doc/ringbuffer_app.html @@ -1,43 +1,257 @@ - - - - -Module ringbuffer_app - - - - -
    - -

    Module ringbuffer_app

    -RingBuffer application. -

    Copyright © 2021 Marc Worrell

    - -

    Behaviours: application.

    -

    Authors: Marc Worrell (marc@worrell.nl).

    - -

    Description

    RingBuffer application -

    Function Index

    - - -
    start/2Application callback, start the ringbuffer supervisor.
    stop/1Application callback, called when stopping the application.
    - -

    Function Details

    - -

    start/2

    -
    -

    start(StartType, StartArgs) -> any()

    -

    -

    Application callback, start the ringbuffer supervisor.

    - -

    stop/1

    -
    -

    stop(State) -> any()

    -

    -

    Application callback, called when stopping the application.

    -
    - - -

    Generated by EDoc

    - + + + + + + + + + + + ringbuffer_app — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + ringbuffer_app + (ringbuffer v1.2.0+build.18.refca920a0) + +

    + + +
    +

    RingBuffer application

    +
    + +
    + +
    +

    + + + + Summary +

    +
    +

    + Functions +

    + +
    + + +

    Application callback, start the ringbuffer supervisor.

    + +
    + +
    +
    + stop(State) + +
    + +

    Application callback, called when stopping the application.

    + +
    + +
    + +
    + + +
    +

    + + + + Functions +

    +
    +
    + +
    + + + +

    start(StartType, StartArgs)

    + + + + + + +
    + +
    + +

    Application callback, start the ringbuffer supervisor.

    +
    +
    +
    + +
    + + + +

    stop(State)

    + + + + + + +
    + +
    + +

    Application callback, called when stopping the application.

    +
    +
    + +
    +
    + + +
    +
    +
    + + diff --git a/doc/ringbuffer_process.html b/doc/ringbuffer_process.html index 04654a5..8de6679 100644 --- a/doc/ringbuffer_process.html +++ b/doc/ringbuffer_process.html @@ -1,117 +1,509 @@ - - - - -Module ringbuffer_process - - - - -
    - -

    Module ringbuffer_process

    -Process to own the created ets table for the ring buffer. -

    Copyright © 2021 Marc Worrell

    - -

    Behaviours: gen_server.

    -

    Authors: Marc Worrell (marc@worrell.nl).

    - -

    Description

    Process to own the created ets table for the ring buffer. -

    Function Index

    - - - - - - - - - - -
    code_change/3
    handle_call/3
    handle_cast/2
    handle_info/2
    init/1
    process_pid/1Find the process pid for the process owning the ets table.
    read/1Read a payload from the buffer.
    start_link/2Create a new process managing a ringbuffer.
    terminate/2
    write/2Write a payload the buffer.
    - -

    Function Details

    - -

    code_change/3

    -
    -

    code_change(OldVsn, State, Extra) -> any()

    -

    -
    + + + + + + + + -

    handle_call/3

    -
    -

    handle_call(X1, From, State) -> any()

    -

    -
    -

    handle_cast/2

    -
    -

    handle_cast(Msg, State) -> any()

    -

    -
    + ringbuffer_process — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + ringbuffer_process + (ringbuffer v1.2.0+build.18.refca920a0) + +

    + + +
    +

    Process to own the created ets table for the ring buffer.

    +
    -

    handle_info/2

    -
    -

    handle_info(Info, State) -> any()

    -

    -

    init/1

    -
    -

    init(X1) -> any()

    -

    +
    +

    + + + + Summary +

    +
    +

    + Functions +

    + + + + + + + + + +
    +
    + init(_) + +
    + +
    + +
    + + +

    Find the process pid for the process owning the ets table. If the buffer does not exist then an error is returned.

    + +
    + +
    +
    + read(Name) + +
    + +

    Read a payload from the buffer. Skip entries that are deleted by the writers.

    + +
    + +
    + + +

    Create a new process managing a ringbuffer.

    + +
    + + + +
    + + +

    Write a payload the buffer. If the readers can't keep up then older entries are deleted.

    + +
    +
    -

    process_pid/1

    -
    -

    process_pid(Name::atom()) -> {ok, pid()} | {error, badarg}

    -

    -

    Find the process pid for the process owning the ets table. If the buffer - does not exist then an error is returned.

    - -

    read/1

    -
    -

    read(Name::atom()) -> {ok, {Skipped::pos_integer(), Payload::term()}} | {error, empty}

    -

    -

    Read a payload from the buffer. Skip entries that are deleted -by the writers.

    - -

    There are a coupe of race conditions we need to take care of:

    - -

    1. Writer incremented -> Reader tries entry --> Writer writes entry -In this case the w-value read by the reader is Size smaller than that -of the writer. In this case we wait till the writer finishes writing.

    - -

    2. Two or more readers arrive at the same time, incrementing the reader value. -One of the readers will have the correct value and can fetch the next entry. -In this case the reader can move past the writer if there are not enough -entries in the buffer for all readers.

    - - For the case where multiple readers are racing past the writer can not be solved - without synchronization, we let the ringbuffer process handle the reader increment. -

    - -

    start_link/2

    -
    -

    start_link(Name::atom(), Size::pos_integer()) -> {ok, pid()} | {error, term()}

    -

    -

    Create a new process managing a ringbuffer.

    - -

    terminate/2

    -
    -

    terminate(Reason, State) -> any()

    -

    +
    + + +
    +

    + + + + Functions +

    +
    +
    + +
    + + + +

    code_change(OldVsn, State, Extra)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    handle_call(_, From, State)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    handle_cast(Msg, State)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    handle_info(Info, State)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    init(_)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    process_pid(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec process_pid(Name :: atom()) -> {ok, pid()} | {error, badarg}.
    + +
    + +

    Find the process pid for the process owning the ets table. If the buffer does not exist then an error is returned.

    +
    +
    +
    + +
    + + + +

    read(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec read(Name :: atom()) -> {ok, {Skipped :: non_neg_integer(), Payload :: term()}} | {error, empty}.
    + +
    + +

    Read a payload from the buffer. Skip entries that are deleted by the writers.

    There are a coupe of race conditions we need to take care of:

    1. Writer incremented -> Reader tries entry --> Writer writes entry In this case the w-value read by the reader is Size smaller than that of the writer. In this case we wait till the writer finishes writing.

    2. Two or more readers arrive at the same time, incrementing the reader value. One of the readers will have the correct value and can fetch the next entry. In this case the reader can move past the writer if there are not enough entries in the buffer for all readers.

    For the case where multiple readers are racing past the writer can not be solved without synchronization, we let the ringbuffer process handle the reader increment.

    +
    +
    +
    + +
    + + + +

    start_link(Name, Size)

    + + + + + + +
    + +
    + +
    + +
    -spec start_link(atom(), pos_integer()) -> {ok, pid()} | {error, term()}.
    + +
    + +

    Create a new process managing a ringbuffer.

    +
    +
    +
    + +
    + + + +

    terminate(Reason, State)

    + + + + + + +
    + +
    + + +
    +
    +
    + +
    + + + +

    write(Name, Payload)

    + + + + + + +
    + +
    + +
    + +
    -spec write(Name :: atom(), Payload :: term()) -> ok.
    + +
    + +

    Write a payload the buffer. If the readers can't keep up then older entries are deleted.

    +
    +
    + +
    +
    + + +
    +
    -

    write/2

    -
    -

    write(Name::atom(), Payload::term()) -> ok

    -

    -

    Write a payload the buffer. If the readers can't keep up then - older entries are deleted.

    -
    - - -

    Generated by EDoc

    - + diff --git a/doc/ringbuffer_sup.html b/doc/ringbuffer_sup.html index 14fa162..2ff7981 100644 --- a/doc/ringbuffer_sup.html +++ b/doc/ringbuffer_sup.html @@ -1,58 +1,365 @@ - - - - -Module ringbuffer_sup - - - - -
    - -

    Module ringbuffer_sup

    -Supervisor for the ring buffers processes. -

    Copyright © 2021 Marc Worrell

    - -

    Behaviours: supervisor.

    -

    Authors: Marc Worrell (marc@worrell.nl).

    - -

    Description

    Supervisor for the ring buffers processes. -

    Function Index

    - - - - -
    init/1Supervisor callback, initialize the children.
    start_child/2Start a ringbuffer.
    start_link/0Start the simple_one_for_one supervisor for the ring buffer processes.
    stop_child/1Stop a ringbuffer.
    - -

    Function Details

    - -

    init/1

    -
    -

    init(X1) -> any()

    -

    -

    Supervisor callback, initialize the children.

    - -

    start_child/2

    -
    -

    start_child(Name::atom(), Size::pos_integer()) -> {ok, pid()} | {error, term()}

    -

    -

    Start a ringbuffer.

    - -

    start_link/0

    -
    -

    start_link() -> any()

    -

    -

    Start the simple_one_for_one supervisor for the ring buffer processes.

    - -

    stop_child/1

    -
    -

    stop_child(Name::atom()) -> ok | {error, not_found}

    -

    -

    Stop a ringbuffer. The managing process is removed from the supervisor and the - ets table is released.

    -
    - - -

    Generated by EDoc

    - + + + + + + + + + + + ringbuffer_sup — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + +
    +

    + + + + View Source + + + ringbuffer_sup + (ringbuffer v1.2.0+build.18.refca920a0) + +

    + + +
    +

    Supervisor for the ring buffers processes.

    +
    + +
    + +
    +

    + + + + Summary +

    +
    +

    + Functions +

    + +
    + + +

    Find the Pid of the ringbuffer with a certain name.

    + +
    + +
    +
    + init(_) + +
    + +

    Supervisor callback, initialize the children.

    + +
    + +
    + + +

    Start a ringbuffer.

    + +
    + +
    +
    + start_link() + +
    + +

    Start the simple_one_for_one supervisor for the ring buffer processes.

    + +
    + +
    + + +

    Stop a ringbuffer. The managing process is removed from the supervisor and the ets table is released.

    + +
    + +
    + +
    + + +
    +

    + + + + Functions +

    +
    +
    + +
    + + + +

    find_child(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec find_child(Name :: atom()) -> {ok, pid()} | {error, not_found}.
    + +
    + +

    Find the Pid of the ringbuffer with a certain name.

    +
    +
    +
    + +
    + + + +

    init(_)

    + + + + + + +
    + +
    + +

    Supervisor callback, initialize the children.

    +
    +
    +
    + +
    + + + +

    start_child(Name, Size)

    + + + + + + +
    + +
    + +
    + +
    -spec start_child(Name :: atom(), Size :: pos_integer()) -> {ok, pid()} | {error, term()}.
    + +
    + +

    Start a ringbuffer.

    +
    +
    +
    + +
    + + + +

    start_link()

    + + + + + + +
    + +
    + +

    Start the simple_one_for_one supervisor for the ring buffer processes.

    +
    +
    +
    + +
    + + + +

    stop_child(Name)

    + + + + + + +
    + +
    + +
    + +
    -spec stop_child(Name :: atom()) -> ok | {error, not_found}.
    + +
    + +

    Stop a ringbuffer. The managing process is removed from the supervisor and the ets table is released.

    +
    +
    + +
    +
    + + +
    +
    +
    + + diff --git a/doc/search.html b/doc/search.html new file mode 100644 index 0000000..23314fe --- /dev/null +++ b/doc/search.html @@ -0,0 +1,158 @@ + + + + + + + + + + + + + Search — ringbuffer v1.2.0+build.18.refca920a0 + + + + + + + + + + + + + +
    + + + + + +
    + + +
    + + + + + +
    +
    +
    + + + diff --git a/doc/stylesheet.css b/doc/stylesheet.css deleted file mode 100644 index ab170c0..0000000 --- a/doc/stylesheet.css +++ /dev/null @@ -1,55 +0,0 @@ -/* standard EDoc style sheet */ -body { - font-family: Verdana, Arial, Helvetica, sans-serif; - margin-left: .25in; - margin-right: .2in; - margin-top: 0.2in; - margin-bottom: 0.2in; - color: #000000; - background-color: #ffffff; -} -h1,h2 { - margin-left: -0.2in; -} -div.navbar { - background-color: #add8e6; - padding: 0.2em; -} -h2.indextitle { - padding: 0.4em; - background-color: #add8e6; -} -h3.function,h3.typedecl { - background-color: #add8e6; - padding-left: 1em; -} -div.spec { - margin-left: 2em; - background-color: #eeeeee; -} -a.module { - text-decoration:none -} -a.module:hover { - background-color: #eeeeee; -} -ul.definitions { - list-style-type: none; -} -ul.index { - list-style-type: none; - background-color: #eeeeee; -} - -/* - * Minor style tweaks - */ -ul { - list-style-type: square; -} -table { - border-collapse: collapse; -} -td { - padding: 3 -} diff --git a/rebar.config b/rebar.config index d7b9b94..ae0df50 100644 --- a/rebar.config +++ b/rebar.config @@ -5,6 +5,8 @@ warn_unused_import ]}. +{project_plugins, [rebar3_hex, rebar3_ex_doc]}. + {deps, [ ]}. @@ -13,3 +15,23 @@ {xref_checks, [undefined_function_calls, locals_not_used, deprecated_function_calls]}. + +{edoc_opts, [ + {preprocess, true}, + {stylesheet, "style.css"} +]}. + +{hex, [ + {doc, #{provider => ex_doc}} +]}. + +{ex_doc, [ + {extras, [ + {"README.md", #{title => "Overview"}}, + {"LICENSE", #{title => "License"}} + ]}, + {main, "README.md"}, + {source_url, "https://github.com/zotonic/ringbuffer"}, + {assets, #{ "assets" => "assets"}}, + {api_reference, true} +]}. \ No newline at end of file diff --git a/src/ringbuffer.erl b/src/ringbuffer.erl index be3f688..f171ac5 100644 --- a/src/ringbuffer.erl +++ b/src/ringbuffer.erl @@ -1,5 +1,5 @@ %% @author Marc Worrell -%% @copyright 2021 Marc Worrell +%% @copyright 2021-2025 Marc Worrell %% @doc Ringbuffer implements a length limited queue. In systems this is %% often implemented as a ring, or cylic, buffer. Where the writer can %% push the reader ahead if the buffer is full. @@ -26,8 +26,9 @@ %%
  • As many queues as needed.
  • %% %% +%% @end -%% Copyright 2021 Marc Worrell +%% Copyright 2021-2025 Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -46,6 +47,7 @@ -export([ start/0, new/2, + whereis/1, delete/1, write/2, read/1 @@ -63,21 +65,40 @@ start() -> %% @doc Create a new named buffer of Size entries. The name must be unique for all ets tables. %% The name must be an atom, and is used for the name of the ets table. A process owning the %% ets table and synchronizing the readers is added to ringbuffer_sup. --spec new( Name :: atom(), Size :: pos_integer() ) -> {ok, pid()} | {error, term()}. -new( Name, Size ) -> - ringbuffer_sup:start_child(Name, Size). +-spec new( Name, Size ) -> {ok, pid()} | {error, Reason} when + Name :: atom(), + Size :: pos_integer(), + Reason :: {already_started, pid()} | term(). +new(Name, Size) -> + case ?MODULE:whereis(Name) of + undefined -> + ringbuffer_sup:start_child(Name, Size); + Pid -> + {error, {already_started, Pid}} + end. +%% @doc Find the ringbuffer with a certain name, return the pid if found, otherwise undefined. +-spec whereis(Name) -> pid() | undefined when + Name :: atom(). +whereis(Name) -> + case ringbuffer_process:process_pid(Name) of + {ok, Pid} -> Pid; + {error, _} -> undefined + end. %% @doc Delete a named ringbuffer, all queued data is destroyed. The ets table and the %% synchronizing process are deleted. --spec delete( Name :: atom() ) -> ok | {error, not_found}. +-spec delete(Name) -> ok | {error, not_found} when + Name :: atom(). delete(Name) -> ringbuffer_sup:stop_child(Name). %% @doc Add an entry to the named ringbuffer. Never fails, if the ringbuffer %% is full then older entries are overwritten. --spec write( Name :: atom(), Payload :: term() ) -> ok. +-spec write(Name, Payload) -> ok when + Name :: atom(), + Payload :: term(). write(Name, Payload) -> ringbuffer_process:write(Name, Payload). @@ -85,7 +106,10 @@ write(Name, Payload) -> %% the payload of the entry read. An entry is skipped if the readers are falling behind the %% writers by more that the size of the buffer. {error, empty} is returned if the %% buffer is empty. --spec read( Name :: atom() ) -> {ok, {non_neg_integer(), term()}} | {error, empty}. +-spec read( Name ) -> {ok, {SkipCount, Payload}} | {error, empty} when + Name :: atom(), + SkipCount :: non_neg_integer(), + Payload :: term(). read(Name) -> ringbuffer_process:read(Name). diff --git a/src/ringbuffer_app.erl b/src/ringbuffer_app.erl index b6806d8..fca63af 100644 --- a/src/ringbuffer_app.erl +++ b/src/ringbuffer_app.erl @@ -1,8 +1,9 @@ %% @author Marc Worrell -%% @copyright 2021 Marc Worrell +%% @copyright 2021-2025 Marc Worrell %% @doc RingBuffer application +%% @end -%% Copyright 2021 Marc Worrell +%% Copyright 2021-2025 Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/src/ringbuffer_process.erl b/src/ringbuffer_process.erl index 98e80c8..1fee61d 100644 --- a/src/ringbuffer_process.erl +++ b/src/ringbuffer_process.erl @@ -1,8 +1,9 @@ %% @author Marc Worrell -%% @copyright 2021 Marc Worrell +%% @copyright 2021-2025 Marc Worrell %% @doc Process to own the created ets table for the ring buffer. +%% @end -%% Copyright 2021 Marc Worrell +%% Copyright 2021-2025 Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/src/ringbuffer_sup.erl b/src/ringbuffer_sup.erl index 306b407..8d6676a 100644 --- a/src/ringbuffer_sup.erl +++ b/src/ringbuffer_sup.erl @@ -1,8 +1,9 @@ %% @author Marc Worrell -%% @copyright 2021 Marc Worrell +%% @copyright 2021-2025 Marc Worrell %% @doc Supervisor for the ring buffers processes. +%% @end -%% Copyright 2021 Marc Worrell +%% Copyright 2021-2025 Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,7 +23,7 @@ %% API -export([start_link/0]). --export([start_child/2, stop_child/1]). +-export([start_child/2, find_child/1, stop_child/1]). %% Supervisor callbacks -export([init/1]). @@ -50,11 +51,12 @@ stop_child(Name) -> {error, _} -> {error, not_found} end. +%% @doc Find the Pid of the ringbuffer with a certain name. +-spec find_child( Name :: atom() ) -> {ok, pid()} | {error, not_found}. find_child(Name) -> - try - ringbuffer_process:process_pid(Name) - catch - error:badarg -> {error, not_found} + case ringbuffer_process:process_pid(Name) of + {ok, _} = Ok -> Ok; + {error, badarg} -> {error, not_found} end. %% =================================================================== diff --git a/test/ringbuffer_test.erl b/test/ringbuffer_test.erl index f5b806d..171499d 100644 --- a/test/ringbuffer_test.erl +++ b/test/ringbuffer_test.erl @@ -1,8 +1,9 @@ %% @author Marc Worrell -%% @copyright 2021 Marc Worrell +%% @copyright 2021-2025 Marc Worrell %% @doc Tests for ringbuffer +%% @end -%% Copyright 2021 Marc Worrell +%% Copyright 2021-2025 Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,7 +27,7 @@ all_test_() -> [ fun test_simple/0 , fun test_full/0 , fun test_race/0 - , fun test_busy/0 + , {timeout, 60, fun test_busy/0} ]}. setup() -> @@ -57,6 +58,8 @@ test_full() -> ok = ringbuffer:delete(full), ok. +%% Test with many concurrent writers, all messages should be +%% queued (and no overflow as the buffer is larger). test_race() -> {ok, _} = ringbuffer:new(race, 10000), Self = self(), @@ -79,6 +82,7 @@ test_race() -> ok. +%% Test with many concurrent readers and writers test_busy() -> {ok, _} = ringbuffer:new(busy, 100), NMsgs = 10000,