<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
      <title>Andrew Gallant&#39;s Blog on Andrew Gallant&#39;s Blog </title>
      <generator uri="https://gohugo.io">Hugo</generator>
    <link>https://blog.burntsushi.net/</link>
    <language>en-us</language>
    
    
    <updated>Wed, 05 Jul 2023 09:06:00 EDT</updated>
    
    <item>
      <title>Regex engine internals as a library</title>
      <link>https://blog.burntsushi.net/regex-internals/</link>
      <pubDate>Wed, 05 Jul 2023 09:06:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/regex-internals/</guid>
      <description>&lt;p&gt;Over the last several years, I&amp;rsquo;ve rewritten &lt;a href=&#34;https://github.com/rust-lang/regex/&#34;&gt;Rust&amp;rsquo;s &lt;code&gt;regex&lt;/code&gt;
crate&lt;/a&gt; to enable better internal composition, and to make it
easier to add optimizations while maintaining correctness. In the course of
this rewrite I created a new crate, &lt;a href=&#34;https://github.com/rust-lang/regex/tree/master/regex-automata&#34;&gt;&lt;code&gt;regex-automata&lt;/code&gt;&lt;/a&gt;, which exposes much
of the &lt;code&gt;regex&lt;/code&gt; crate internals as their own APIs for others to use. To my
knowledge, this is the first regex library to expose its internals to the
degree done in &lt;code&gt;regex-automata&lt;/code&gt; as a separately versioned library.&lt;/p&gt;
&lt;p&gt;This blog post discusses the problems that led to the rewrite, how the rewrite
solved them and a guided tour of &lt;code&gt;regex-automata&lt;/code&gt;&amp;rsquo;s API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Rust programmers and anyone with an interest in how one
particular finite automata regex engine is implemented. Prior experience with
regular expressions is assumed.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A byte string library for Rust</title>
      <link>https://blog.burntsushi.net/bstr/</link>
      <pubDate>Wed, 07 Sep 2022 14:00:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/bstr/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://docs.rs/bstr/1.*&#34;&gt;&lt;code&gt;bstr&lt;/code&gt;&lt;/a&gt; is a byte string library for Rust and &lt;a href=&#34;https://github.com/BurntSushi/bstr/releases/tag/1.0.0&#34;&gt;its 1.0 version has
just been released&lt;/a&gt;! It provides string oriented operations on
arbitrary sequences of bytes, but is most useful when those bytes are UTF-8. In
other words, it provides a string type that is UTF-8 by &lt;em&gt;convention&lt;/em&gt;, where as
Rust&amp;rsquo;s built-in string types are &lt;em&gt;guaranteed&lt;/em&gt; to be UTF-8.&lt;/p&gt;
&lt;p&gt;This blog will briefly describe the API, do a deep dive on the motivation for
creating &lt;code&gt;bstr&lt;/code&gt;, show some short example programs using &lt;code&gt;bstr&lt;/code&gt; and conclude
with a few thoughts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Rust programmers with some background knowledge of UTF-8.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Using unwrap() in Rust is Okay</title>
      <link>https://blog.burntsushi.net/unwrap/</link>
      <pubDate>Mon, 08 Aug 2022 09:00:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/unwrap/</guid>
      <description>&lt;p&gt;One day before Rust 1.0 was released, I published a
&lt;a href=&#34;https://blog.burntsushi.net/rust-error-handling/&#34;&gt;blog post covering the fundamentals of error handling&lt;/a&gt;.
A particularly important but small section buried in the middle of the article
is named &amp;ldquo;&lt;a href=&#34;https://blog.burntsushi.net/rust-error-handling/#a-brief-interlude-unwrapping-isnt-evil&#34;&gt;unwrapping isn&amp;rsquo;t evil&lt;/a&gt;&amp;rdquo;. That section briefly
described that, broadly speaking, using &lt;code&gt;unwrap()&lt;/code&gt; is okay if it&amp;rsquo;s in
test/example code or when panicking indicates a bug.&lt;/p&gt;
&lt;p&gt;I generally still hold that belief today. That belief is put into practice in
Rust&amp;rsquo;s standard library and in many core ecosystem crates. (And that practice
predates my blog post.) Yet, there still seems to be widespread confusion about
when it is and isn&amp;rsquo;t okay to use &lt;code&gt;unwrap()&lt;/code&gt;. This post will talk about that
in more detail and respond specifically to a number of positions I&amp;rsquo;ve seen
expressed.&lt;/p&gt;
&lt;p&gt;This blog post is written somewhat as a FAQ, but it&amp;rsquo;s meant to be read in
sequence. Each question builds on the one before it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Primarily Rust programmers, but I&amp;rsquo;ve hopefully provided
enough context that the principles espoused here apply to any programmer.
Although it may be tricky to apply an obvious mapping to languages with
different error handling mechanisms, such as exceptions.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Archlinux on the System76 Darter Pro</title>
      <link>https://blog.burntsushi.net/system76-darter-archlinux/</link>
      <pubDate>Mon, 27 Jan 2020 17:55:00 EST</pubDate>
      
      <guid>https://blog.burntsushi.net/system76-darter-archlinux/</guid>
      <description>&lt;p&gt;This is a quick post reviewing my Archlinux setup on a System76 Darter Pro
(model: darp6) with Coreboot, along with some thoughts about the laptop in
general. This is my first laptop upgrade since I
&lt;a href=&#34;https://blog.burntsushi.net/lenovo-thinkpad-t430-archlinux&#34;&gt;purchased a ThinkPad T430 in July 2012&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Target audience: Archlinux users looking for a compatible Linux laptop.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>My FOSS Story</title>
      <link>https://blog.burntsushi.net/foss/</link>
      <pubDate>Sun, 19 Jan 2020 17:15:00 EST</pubDate>
      
      <guid>https://blog.burntsushi.net/foss/</guid>
      <description>&lt;p&gt;I&amp;rsquo;d like to break from my normal tradition of focusing almost strictly on
technical content and share a bit of my own personal relationship with Free
and Open Source Software (FOSS). While everyone is different, my hope is that
sharing my perspective will help build understanding, empathy and trust.&lt;/p&gt;
&lt;p&gt;This is not meant to be a direct response to the behavior of any other
maintainer. Nor should it be read as a prescription on the ideal behavior of
someone in FOSS. This is meant more as a personal reflection with the hope that
others will use it to reflect on their own relationship with FOSS. There is no
one true path to being a good FOSS maintainer. We all have our own coping
mechanisms.&lt;/p&gt;
&lt;p&gt;This is also emphatically not meant as a call for help. This is about
understanding. This is not about a plea to change the economics of FOSS. This
is not about brainstorming ways to improve my mental health. This is not about
bringing on more maintainers. It&amp;rsquo;s about sharing my story and attempting to
increase empathy among the denizens of FOSS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Anyone involved in FOSS.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Rust and CSV parsing</title>
      <link>https://blog.burntsushi.net/csv/</link>
      <pubDate>Mon, 22 May 2017 21:01:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/csv/</guid>
      <description>&lt;p&gt;With &lt;code&gt;csv 1.0&lt;/code&gt; just released, the time is ripe for a tutorial on how to read
and write CSV data in Rust. This tutorial is targeted toward beginning Rust
programmers, and is therefore full of examples and spends some time on basic
concepts. Experienced Rust programmers may find parts of this useful, but would
probably be happier with a quick skim.&lt;/p&gt;
&lt;p&gt;For an introduction to Rust, please see the
&lt;a href=&#34;https://doc.rust-lang.org/book/second-edition/&#34;&gt;official book&lt;/a&gt;.
If you haven&amp;rsquo;t written any Rust code yet but have written code in another
language, then this tutorial might be accessible to you without needing to read
the book first.&lt;/p&gt;
&lt;p&gt;The CSV library is
&lt;a href=&#34;https://github.com/BurntSushi/rust-csv&#34;&gt;available on Github&lt;/a&gt;
and has
&lt;a href=&#34;https://docs.rs/csv&#34;&gt;comprehensive API documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, a version of this blog post is included as a
&lt;a href=&#34;https://docs.rs/csv/1.0.0/csv/tutorial/index.html&#34;&gt;tutorial&lt;/a&gt;
in the API documentation, and is more likely to be updated as time passes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Beginning Rust programmers.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>ripgrep is faster than {grep, ag, git grep, ucg, pt, sift}</title>
      <link>https://blog.burntsushi.net/ripgrep/</link>
      <pubDate>Fri, 23 Sep 2016 07:05:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/ripgrep/</guid>
      <description>&lt;p&gt;In this article I will introduce a new command line search tool,
&lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/a&gt;,
that combines the usability of
&lt;a href=&#34;https://github.com/ggreer/the_silver_searcher&#34;&gt;The Silver Searcher&lt;/a&gt;
(an &lt;a href=&#34;http://beyondgrep.com/&#34;&gt;&lt;code&gt;ack&lt;/code&gt;&lt;/a&gt; clone) with the
raw performance of GNU grep. &lt;code&gt;ripgrep&lt;/code&gt; is fast, cross platform (with binaries
available for Linux, Mac and Windows) and written in
&lt;a href=&#34;https://www.rust-lang.org&#34;&gt;Rust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ripgrep&lt;/code&gt; is available on
&lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We will attempt to do the impossible: a fair benchmark comparison between
several popular code search tools. Specifically, we will dive into a series of
25 benchmarks that substantiate the following claims:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For both searching single files &lt;em&gt;and&lt;/em&gt; huge directories of files, no other
tool obviously stands above &lt;code&gt;ripgrep&lt;/code&gt; in either performance or correctness.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ripgrep&lt;/code&gt; is the only tool with proper Unicode support that doesn&amp;rsquo;t make
you pay dearly for it.&lt;/li&gt;
&lt;li&gt;Tools that search many files at once are generally &lt;em&gt;slower&lt;/em&gt; if they use
memory maps, not faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As someone who has worked on text search in Rust in their free time for the
last 2.5 years, and as the author of both &lt;code&gt;ripgrep&lt;/code&gt; and
&lt;a href=&#34;https://github.com/rust-lang-nursery/regex&#34;&gt;the underlying regular expression engine&lt;/a&gt;,
I will use this opportunity to provide detailed insights into the performance
of each code search tool. No benchmark will go unscrutinized!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Some familiarity with Unicode, programming and some
experience with working on the command line.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I&amp;rsquo;m hearing reports from some people that &lt;code&gt;rg&lt;/code&gt; isn&amp;rsquo;t as fast as I&amp;rsquo;ve
claimed on their data. I&amp;rsquo;d love to help explain what&amp;rsquo;s going on, but to do
that, I&amp;rsquo;ll need to be able to reproduce your results. If you
&lt;a href=&#34;https://github.com/BurntSushi/ripgrep/issues&#34;&gt;file an issue&lt;/a&gt;
with something I can reproduce, I&amp;rsquo;d be happy to try and explain it.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Index 1,600,000,000 Keys with Automata and Rust</title>
      <link>https://blog.burntsushi.net/transducers/</link>
      <pubDate>Wed, 11 Nov 2015 22:45:00 -0400</pubDate>
      
      <guid>https://blog.burntsushi.net/transducers/</guid>
      <description>&lt;p&gt;It turns out that finite state machines are useful for things other than
expressing computation. Finite state machines can also be used to compactly
represent ordered sets or maps of strings that can be searched very quickly.&lt;/p&gt;
&lt;p&gt;In this article, I will teach you about finite state machines as a &lt;em&gt;data
structure&lt;/em&gt; for representing ordered sets and maps. This includes introducing
an implementation written in Rust called the
&lt;a href=&#34;https://github.com/BurntSushi/fst&#34;&gt;&lt;code&gt;fst&lt;/code&gt; crate&lt;/a&gt;.
It comes with
&lt;a href=&#34;https://burntsushi.net/rustdoc/fst/&#34;&gt;complete API documentation&lt;/a&gt;.
I will also show you how to build them using a simple command line tool.
Finally, I will discuss a few experiments culminating in indexing over
1,600,000,000 URLs (134 GB) from the
&lt;a href=&#34;http://blog.commoncrawl.org/2015/08/july-2015-crawl-archive-available/&#34;&gt;July 2015 Common Crawl Archive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The technique presented in this article is also how
&lt;a href=&#34;http://blog.mikemccandless.com/2010/12/using-finite-state-transducers-in.html&#34;&gt;Lucene represents a part of its inverted
index&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Along the way, we will talk about memory maps, automaton intersection with
regular expressions, fuzzy searching with Levenshtein distance and streaming
set operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Some familiarity with programming and fundamental data
structures. No experience with automata theory or Rust is required.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Error Handling in Rust</title>
      <link>https://blog.burntsushi.net/rust-error-handling/</link>
      <pubDate>Thu, 14 May 2015 10:47:26 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/rust-error-handling/</guid>
      <description>&lt;p&gt;Like most programming languages, Rust encourages the programmer to handle
errors in a particular way. Generally speaking, error handling is divided into
two broad categories: exceptions and return values. Rust opts for return
values.&lt;/p&gt;
&lt;p&gt;In this article, I intend to provide a comprehensive treatment of how to deal
with errors in Rust. More than that, I will attempt to introduce error handling
one piece at a time so that you&amp;rsquo;ll come away with a solid working knowledge of
how everything fits together.&lt;/p&gt;
&lt;p&gt;When done naively, error handling in Rust can be verbose and annoying. This
article will explore those stumbling blocks and demonstrate how to use the
standard library to make error handling concise and ergonomic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target audience&lt;/strong&gt;: Those new to Rust that don&amp;rsquo;t know its error handling
idioms yet. Some familiarity with Rust is helpful. (This article makes heavy
use of some standard traits and some very light use of closures and macros.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (2018/04/14)&lt;/strong&gt;: Examples were converted to &lt;code&gt;?&lt;/code&gt;, and some text was
added to give historical context on the change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (2020/01/03)&lt;/strong&gt;: A recommendation to use
&lt;a href=&#34;https://crates.io/crates/failure&#34;&gt;&lt;code&gt;failure&lt;/code&gt;&lt;/a&gt; was removed and replaced with
a recommendation to use either &lt;code&gt;Box&amp;lt;Error + Send + Sync&amp;gt;&lt;/code&gt; or
&lt;a href=&#34;https://crates.io/crates/anyhow&#34;&gt;&lt;code&gt;anyhow&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Syntax extensions and regular expressions for Rust</title>
      <link>https://blog.burntsushi.net/rust-regex-syntax-extensions/</link>
      <pubDate>Mon, 21 Apr 2014 19:51:00 EDT</pubDate>
      
      <guid>https://blog.burntsushi.net/rust-regex-syntax-extensions/</guid>
      <description>&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; &lt;!-- raw HTML omitted --&gt;2018-04-12&lt;!-- raw HTML omitted --&gt;: The code snippets for this post are no longer
available. This is just as well anyway, since they all depended on an unstable
internal compiler interface, which hasn&amp;rsquo;t existed for years.&lt;/p&gt;
&lt;p&gt;A few weeks ago, I set out to add regular expressions to the
&lt;a href=&#34;http://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt;
distribution with an implementation and feature set heavily inspired by
&lt;a href=&#34;http://swtch.com/~rsc/regexp/&#34;&gt;Russ Cox&amp;rsquo;s RE2&lt;/a&gt;.
It was just recently added to the
&lt;a href=&#34;http://static.rust-lang.org/doc/master/regex/index.html&#34;&gt;Rust distribution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This regex crate includes a syntax extension that compiles a regular expression
to native Rust code &lt;em&gt;when a Rust program is compiled&lt;/em&gt;. This can be thought of
as &amp;ldquo;ahead of time&amp;rdquo; compilation or
something similar to &lt;a href=&#34;http://en.wikipedia.org/wiki/Compile_time_function_execution&#34;&gt;compile time function
execution&lt;/a&gt;.
These special natively compiled regexes have the &lt;em&gt;same exact&lt;/em&gt; API as regular
expressions compiled at runtime.&lt;/p&gt;
&lt;p&gt;In this article, I will outline my implementation strategy&amp;mdash;including code
samples on how to write a Rust syntax extension&amp;mdash;and describe how I was able
to achieve an identical API between regexes compiled at compile time and
regexes compiled at runtime.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Writing type parametric functions in Go</title>
      <link>https://blog.burntsushi.net/type-parametric-functions-golang/</link>
      <pubDate>Sat, 06 Apr 2013 12:54:00 -0500</pubDate>
      
      <guid>https://blog.burntsushi.net/type-parametric-functions-golang/</guid>
      <description>&lt;p&gt;Go&amp;rsquo;s only method of compile time safe polymorphism is structural subtyping, and
this article will do nothing to change that. Instead, I&amp;rsquo;m going to present a
package &lt;code&gt;ty&lt;/code&gt; with facilities to write type parametric functions in Go that
maintain &lt;strong&gt;run time&lt;/strong&gt; type safety, while also being convenient for the
caller to use.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Introducing NFLGame: Programmatic access to live NFL game statistics</title>
      <link>https://blog.burntsushi.net/nfl-live-statistics-with-python/</link>
      <pubDate>Thu, 30 Aug 2012 00:45:00 -0500</pubDate>
      
      <guid>https://blog.burntsushi.net/nfl-live-statistics-with-python/</guid>
      <description>&lt;p&gt;As a programmer and a fantasy football addict, I am embarassed by the means
through which we must expend ourselves to get data in a machine readable form.
This lack of open source software cripples the community with sub-standard
tools, and most importantly, detracts from some really cool and fun things that
could be done with easily available statistics. Many tools are either out-dated
or broken, or if they work, they are closed source and often cost money.&lt;/p&gt;
&lt;p&gt;Yesterday I started work on a new library package that I hope will start to
improve this sorry state of affairs.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Running Archlinux on the Lenovo Thinkpad T430</title>
      <link>https://blog.burntsushi.net/lenovo-thinkpad-t430-archlinux/</link>
      <pubDate>Sun, 01 Jul 2012 00:39:00 -0500</pubDate>
      
      <guid>https://blog.burntsushi.net/lenovo-thinkpad-t430-archlinux/</guid>
      <description>&lt;p&gt;In sum, Archlinux is working beautifully. What follows is a rough run down of
my notes while installing, configuring, tuning and using Archlinux on the
Lenovo Thinkpad T430.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Daemonizing Go Programs (with a BSD-style rc.d example)</title>
      <link>https://blog.burntsushi.net/golang-daemonize-bsd/</link>
      <pubDate>Fri, 27 Apr 2012 21:12:00 -0500</pubDate>
      
      <guid>https://blog.burntsushi.net/golang-daemonize-bsd/</guid>
      <description>&lt;p&gt;Go, by its very nature, is multithreaded. This makes a traditional approach of
daemonizing Go programs by forking a bit difficult.&lt;/p&gt;
&lt;p&gt;To get around this, you could try something as simple as backgrounding your Go
program and instructing it to &lt;a href=&#34;http://en.wikipedia.org/wiki/Nohup&#34;&gt;ignore the HUP
signal&lt;/a&gt;:&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Adding Thread Safety to the X Go Binding</title>
      <link>https://blog.burntsushi.net/thread-safety-x-go-binding/</link>
      <pubDate>Sat, 21 Apr 2012 20:52:00 -0500</pubDate>
      
      <guid>https://blog.burntsushi.net/thread-safety-x-go-binding/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;http://code.google.com/p/x-go-binding/&#34;&gt;X Go Binding (XGB)&lt;/a&gt; is a low level
library that provides an API to interact with running X servers. One can only
communicate with an X server by sending data over a network connection;
protocol requests, replies and errors need to be perfectly constructed down to
the last byte. Xlib did precisely this, and then some. As a result, Xlib became
huge and difficult to maintain.&lt;/p&gt;
&lt;p&gt;In recent years, the &lt;a href=&#34;http://xcb.freedesktop.org/&#34;&gt;XCB project&lt;/a&gt; made things a
bit more civilized by generating C code from &lt;a href=&#34;http://cgit.freedesktop.org/xcb/proto/tree/src&#34;&gt;XML
files&lt;/a&gt; describing the X client
protocol using Python. While &lt;a href=&#34;http://cgit.freedesktop.org/xcb/libxcb/tree/src/c_client.py&#34;&gt;the Python to generate said
code&lt;/a&gt; is no walk
in the park, it is typically preferred to the alternative: keeping the X core
protocol up to date along with any number of extensions that exist as well.
(There are other benefits to XCB, like easier asynchronicity, but that is
beyond the scope of this post.)&lt;/p&gt;
&lt;p&gt;XGB proceeds in a similar vain; &lt;a href=&#34;http://code.google.com/r/jamslam-x-go-binding/source/browse/xgb/go_client.py&#34;&gt;Python is used to generate Go
code&lt;/a&gt;
that provides an API to interact with the X protocol. Unlike its sister project
XCB, it is not thread safe. In particular, if X requests are made in parallel,
the best case scenario is a jumbled request or reply and the worst case
scenario is an X server crash. Parallel requests can be particularly useful
when images are being sent to the X server to be painted on the screen; other
useful work could be done in the interim.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>

